suricata
output-json-file.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Tom DeCanio <td@npulsetech.com>
22  *
23  * Log files we track.
24  *
25  */
26 
27 #include "suricata-common.h"
28 #include "detect.h"
29 #include "pkt-var.h"
30 #include "conf.h"
31 
32 #include "threadvars.h"
33 #include "tm-modules.h"
34 
35 #include "threads.h"
36 
37 #include "app-layer-parser.h"
38 
39 #include "detect-filemagic.h"
40 
41 #include "stream.h"
42 
43 #include "util-print.h"
44 #include "util-privs.h"
45 #include "util-debug.h"
46 #include "util-file.h"
47 #include "util-buffer.h"
48 #include "util-byte.h"
49 #include "util-validate.h"
50 
51 #include "util-logopenfile.h"
52 
53 #include "output.h"
54 #include "output-json.h"
55 #include "output-json-file.h"
56 #include "output-json-http.h"
57 #include "output-json-smtp.h"
59 #include "output-json-nfs.h"
60 #include "output-json-smb.h"
61 
62 #include "app-layer-htp.h"
63 #include "app-layer-htp-xff.h"
64 #include "util-memcmp.h"
65 #include "stream-tcp-reassemble.h"
66 #include "flow.h"
67 
68 typedef struct OutputFileCtx_ {
69  uint32_t file_cnt;
74 
75 typedef struct JsonFileLogThread_ {
79 
80 SCJsonBuilder *JsonBuildFileInfoRecord(const Packet *p, const File *ff, void *tx,
81  const uint64_t tx_id, const bool stored, uint8_t dir, HttpXFFCfg *xff_cfg,
82  OutputJsonCtx *eve_ctx)
83 {
85 
86  switch(dir) {
87  case STREAM_TOCLIENT:
88  fdir = LOG_DIR_FLOW_TOCLIENT;
89  break;
90  case STREAM_TOSERVER:
91  fdir = LOG_DIR_FLOW_TOSERVER;
92  break;
93  default:
95  break;
96  }
97 
99  JsonAddrInfoInit(p, fdir, &addr, &eve_ctx->cfg);
100 
101  /* Overwrite address info with XFF if needed. */
102  int have_xff_ip = 0;
103  char xff_buffer[XFF_MAXLEN];
104  if ((xff_cfg != NULL) && !(xff_cfg->flags & XFF_DISABLED)) {
106  have_xff_ip = HttpXFFGetIPFromTx(p->flow, tx_id, xff_cfg, xff_buffer, XFF_MAXLEN);
107  }
108  if (have_xff_ip && xff_cfg->flags & XFF_OVERWRITE) {
109  if (p->flowflags & FLOW_PKT_TOCLIENT) {
110  strlcpy(addr.dst_ip, xff_buffer, JSON_ADDR_LEN);
111  } else {
112  strlcpy(addr.src_ip, xff_buffer, JSON_ADDR_LEN);
113  }
114  have_xff_ip = 0;
115  }
116  }
117 
118  SCJsonBuilder *js = CreateEveHeader(p, fdir, "fileinfo", &addr, eve_ctx);
119  if (unlikely(js == NULL))
120  return NULL;
121 
122  SCJsonBuilderMark mark = { 0, 0, 0 };
124  switch (p->flow->alproto) {
125  case ALPROTO_HTTP1:
126  SCJbOpenObject(js, "http");
127  EveHttpAddMetadata(p->flow, tx_id, js);
128  SCJbClose(js);
129  break;
130  case ALPROTO_SMTP:
131  SCJbGetMark(js, &mark);
132  SCJbOpenObject(js, "smtp");
133  if (EveSMTPAddMetadata(p->flow, tx_id, js)) {
134  SCJbClose(js);
135  } else {
136  SCJbRestoreMark(js, &mark);
137  }
138  SCJbGetMark(js, &mark);
139  SCJbOpenObject(js, "email");
140  if (EveEmailAddMetadata(p->flow, tx_id, js)) {
141  SCJbClose(js);
142  } else {
143  SCJbRestoreMark(js, &mark);
144  }
145  break;
146  case ALPROTO_NFS:
147  /* rpc */
148  SCJbGetMark(js, &mark);
149  SCJbOpenObject(js, "rpc");
150  if (EveNFSAddMetadataRPC(p->flow, tx_id, js)) {
151  SCJbClose(js);
152  } else {
153  SCJbRestoreMark(js, &mark);
154  }
155  /* nfs */
156  SCJbGetMark(js, &mark);
157  SCJbOpenObject(js, "nfs");
158  if (EveNFSAddMetadata(p->flow, tx_id, js)) {
159  SCJbClose(js);
160  } else {
161  SCJbRestoreMark(js, &mark);
162  }
163  break;
164  case ALPROTO_SMB:
165  SCJbGetMark(js, &mark);
166  SCJbOpenObject(js, "smb");
167  if (EveSMBAddMetadata(p->flow, tx_id, js)) {
168  SCJbClose(js);
169  } else {
170  SCJbRestoreMark(js, &mark);
171  }
172  break;
173  default:
175  if (al && al->LogTx) {
176  void *state = FlowGetAppState(p->flow);
177  if (state) {
178  tx = AppLayerParserGetTx(p->flow->proto, p->flow->alproto, state, tx_id);
179  if (tx) {
180  SCJbGetMark(js, &mark);
181  if (!al->LogTx(tx, js)) {
182  SCJbRestoreMark(js, &mark);
183  }
184  }
185  }
186  }
187  break;
188  }
189 
190  SCJbSetString(js, "app_proto", AppProtoToString(p->flow->alproto));
191 
192  SCJbOpenObject(js, "fileinfo");
193  if (stored) {
194  // the file has just been stored on disk cf OUTPUT_FILEDATA_FLAG_CLOSE
195  // but the flag is not set until the loggers have been called
196  EveFileInfo(js, ff, tx_id, ff->flags | FILE_STORED);
197  } else {
198  EveFileInfo(js, ff, tx_id, ff->flags);
199  }
200  SCJbClose(js);
201 
202  /* xff header */
203  if (have_xff_ip && xff_cfg->flags & XFF_EXTRADATA) {
204  SCJbSetString(js, "xff", xff_buffer);
205  }
206 
207  return js;
208 }
209 
210 /**
211  * \internal
212  * \brief Write meta data on a single line json record
213  */
214 static void FileWriteJsonRecord(ThreadVars *tv, JsonFileLogThread *aft, const Packet *p,
215  const File *ff, void *tx, const uint64_t tx_id, uint8_t dir, OutputJsonCtx *eve_ctx)
216 {
217  HttpXFFCfg *xff_cfg = aft->filelog_ctx->xff_cfg != NULL ? aft->filelog_ctx->xff_cfg
218  : aft->filelog_ctx->parent_xff_cfg;
219  SCJsonBuilder *js = JsonBuildFileInfoRecord(p, ff, tx, tx_id, false, dir, xff_cfg, eve_ctx);
220  if (unlikely(js == NULL)) {
221  return;
222  }
223 
224  OutputJsonBuilderBuffer(tv, p, p->flow, js, aft->ctx);
225  SCJbFree(js);
226 }
227 
228 static int JsonFileLogger(ThreadVars *tv, void *thread_data, const Packet *p, const File *ff,
229  void *tx, const uint64_t tx_id, uint8_t dir)
230 {
231  SCEnter();
232  JsonFileLogThread *aft = (JsonFileLogThread *)thread_data;
233 
235 
236  SCLogDebug("ff %p", ff);
237 
238  FileWriteJsonRecord(tv, aft, p, ff, tx, tx_id, dir, aft->filelog_ctx->eve_ctx);
239  return 0;
240 }
241 
242 
243 static TmEcode JsonFileLogThreadInit(ThreadVars *t, const void *initdata, void **data)
244 {
245  JsonFileLogThread *aft = SCCalloc(1, sizeof(JsonFileLogThread));
246  if (unlikely(aft == NULL))
247  return TM_ECODE_FAILED;
248 
249  if(initdata == NULL)
250  {
251  SCLogDebug("Error getting context for EveLogFile. \"initdata\" argument NULL");
252  goto error_exit;
253  }
254 
255  /* Use the Output Context (file pointer and mutex) */
256  aft->filelog_ctx = ((OutputCtx *)initdata)->data;
257  aft->ctx = CreateEveThreadCtx(t, aft->filelog_ctx->eve_ctx);
258  if (!aft->ctx) {
259  goto error_exit;
260  }
261 
262  *data = (void *)aft;
263  return TM_ECODE_OK;
264 
265 error_exit:
266  SCFree(aft);
267  return TM_ECODE_FAILED;
268 }
269 
270 static TmEcode JsonFileLogThreadDeinit(ThreadVars *t, void *data)
271 {
272  JsonFileLogThread *aft = (JsonFileLogThread *)data;
273  if (aft == NULL) {
274  return TM_ECODE_OK;
275  }
276 
277  FreeEveThreadCtx(aft->ctx);
278 
279  /* clear memory */
280  memset(aft, 0, sizeof(JsonFileLogThread));
281 
282  SCFree(aft);
283  return TM_ECODE_OK;
284 }
285 
286 static void OutputFileLogDeinitSub(OutputCtx *output_ctx)
287 {
288  OutputFileCtx *ff_ctx = output_ctx->data;
289  if (ff_ctx->xff_cfg != NULL) {
290  SCFree(ff_ctx->xff_cfg);
291  }
292  SCFree(ff_ctx);
293  SCFree(output_ctx);
294 }
295 
296 /** \brief Create a new http log LogFileCtx.
297  * \param conf Pointer to ConfNode containing this loggers configuration.
298  * \return NULL if failure, LogFileCtx* to the file_ctx if succesful
299  * */
300 static OutputInitResult OutputFileLogInitSub(SCConfNode *conf, OutputCtx *parent_ctx)
301 {
302  OutputInitResult result = { NULL, false };
303  OutputJsonCtx *ojc = parent_ctx->data;
304 
305  OutputFileCtx *output_file_ctx = SCCalloc(1, sizeof(OutputFileCtx));
306  if (unlikely(output_file_ctx == NULL))
307  return result;
308 
309  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
310  if (unlikely(output_ctx == NULL)) {
311  SCFree(output_file_ctx);
312  return result;
313  }
314 
315  if (conf) {
316  const char *force_filestore = SCConfNodeLookupChildValue(conf, "force-filestore");
317  if (force_filestore != NULL && SCConfValIsTrue(force_filestore)) {
319  SCLogConfig("forcing filestore of all files");
320  }
321 
322  const char *force_magic = SCConfNodeLookupChildValue(conf, "force-magic");
323  if (force_magic != NULL && SCConfValIsTrue(force_magic)) {
325  SCLogConfig("forcing magic lookup for logged files");
326  }
327 
328  FileForceHashParseCfg(conf);
329  }
330 
331  if (conf != NULL && SCConfNodeLookupChild(conf, "xff") != NULL) {
332  output_file_ctx->xff_cfg = SCCalloc(1, sizeof(HttpXFFCfg));
333  if (output_file_ctx->xff_cfg != NULL) {
334  HttpXFFGetCfg(conf, output_file_ctx->xff_cfg);
335  }
336  } else if (ojc->xff_cfg) {
337  output_file_ctx->parent_xff_cfg = ojc->xff_cfg;
338  }
339 
340  output_file_ctx->eve_ctx = ojc;
341  output_ctx->data = output_file_ctx;
342  output_ctx->DeInit = OutputFileLogDeinitSub;
343 
345  result.ctx = output_ctx;
346  result.ok = true;
347  return result;
348 }
349 
351 {
352  /* register as child of eve-log */
353  OutputRegisterFileSubModule(LOGGER_JSON_FILE, "eve-log", "JsonFileLog", "eve-log.files",
354  OutputFileLogInitSub, JsonFileLogger, JsonFileLogThreadInit, JsonFileLogThreadDeinit);
355 }
SCJsonBuilder
struct SCJsonBuilder SCJsonBuilder
Definition: detect-engine-helper.h:83
XFF_MAXLEN
#define XFF_MAXLEN
Definition: app-layer-htp-xff.h:39
util-byte.h
SCOutputJsonLogDirection
SCOutputJsonLogDirection
Definition: output-eve-bindgen.h:33
SCConfValIsTrue
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:577
OutputJsonCtx_::xff_cfg
HttpXFFCfg * xff_cfg
Definition: output-json.h:81
FileForceHashParseCfg
void FileForceHashParseCfg(SCConfNode *conf)
Function to parse forced file hashing configuration.
Definition: util-file.c:169
XFF_EXTRADATA
#define XFF_EXTRADATA
Definition: app-layer-htp-xff.h:31
JsonBuildFileInfoRecord
SCJsonBuilder * JsonBuildFileInfoRecord(const Packet *p, const File *ff, void *tx, const uint64_t tx_id, const bool stored, uint8_t dir, HttpXFFCfg *xff_cfg, OutputJsonCtx *eve_ctx)
Definition: output-json-file.c:80
OutputJsonCtx_::cfg
OutputJsonCommonSettings cfg
Definition: output-json.h:80
HttpXFFGetCfg
void HttpXFFGetCfg(SCConfNode *conf, HttpXFFCfg *result)
Function to return XFF configuration from a configuration node.
Definition: app-layer-htp-xff.c:116
FileForceTrackingEnable
void FileForceTrackingEnable(void)
Definition: util-file.c:161
OutputFileCtx_::eve_ctx
OutputJsonCtx * eve_ctx
Definition: output-json-file.c:72
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
JsonFileLogThread_::ctx
OutputJsonThreadCtx * ctx
Definition: output-json-file.c:77
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
FreeEveThreadCtx
void FreeEveThreadCtx(OutputJsonThreadCtx *ctx)
Definition: output-json-common.c:58
Flow_::proto
uint8_t proto
Definition: flow.h:381
SCFlowGetAppProtocol
AppProto SCFlowGetAppProtocol(const Flow *f)
Definition: flow.c:1288
CreateEveHeader
SCJsonBuilder * CreateEveHeader(const Packet *p, enum SCOutputJsonLogDirection dir, const char *event_type, JsonAddrInfo *addr, OutputJsonCtx *eve_ctx)
Definition: output-json.c:816
threads.h
OutputJsonCtx_
Definition: output-json.h:77
JsonAddrInfoInit
void JsonAddrInfoInit(const Packet *p, enum SCOutputJsonLogDirection dir, JsonAddrInfo *addr, OutputJsonCommonSettings *cfg)
Definition: output-json.c:464
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its normalized string equivalent.
Definition: app-layer-protos.c:53
JsonFileLogRegister
void JsonFileLogRegister(void)
Definition: output-json-file.c:350
CreateEveThreadCtx
OutputJsonThreadCtx * CreateEveThreadCtx(ThreadVars *t, OutputJsonCtx *ctx)
Definition: output-json-common.c:29
json_addr_info_zero
const JsonAddrInfo json_addr_info_zero
Definition: output-json.c:78
tm-modules.h
LOG_DIR_FLOW_TOSERVER
@ LOG_DIR_FLOW_TOSERVER
Definition: output-eve-bindgen.h:37
util-privs.h
stream-tcp-reassemble.h
FileForceMagicEnable
void FileForceMagicEnable(void)
Definition: util-file.c:98
p
Packet * p
Definition: fuzz_dataset.c:30
OutputJsonBuilderBuffer
void OutputJsonBuilderBuffer(ThreadVars *tv, const Packet *p, Flow *f, SCJsonBuilder *js, OutputJsonThreadCtx *ctx)
Definition: output-json.c:1018
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:877
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:547
OutputFileCtx_::xff_cfg
HttpXFFCfg * xff_cfg
Definition: output-json-file.c:70
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
OutputRegisterFileSubModule
void OutputRegisterFileSubModule(LoggerId id, const char *parent_name, const char *name, const char *conf_name, OutputInitSubFunc InitFunc, SCFileLogger FileLogFunc, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit)
Register a file output sub-module.
Definition: output.c:427
EveHttpAddMetadata
bool EveHttpAddMetadata(const Flow *f, uint64_t tx_id, SCJsonBuilder *js)
Definition: output-json-http.c:486
OutputCtx_::data
void * data
Definition: tm-modules.h:91
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
EveSMBAddMetadata
bool EveSMBAddMetadata(const Flow *f, uint64_t tx_id, SCJsonBuilder *jb)
Definition: output-json-smb.c:34
OutputCtx_
Definition: tm-modules.h:88
app-layer-htp-xff.h
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
OutputJsonThreadCtx_
Definition: output-json.h:85
util-memcmp.h
app-layer-htp.h
EveSMTPAddMetadata
bool EveSMTPAddMetadata(const Flow *f, uint64_t tx_id, SCJsonBuilder *js)
Definition: output-json-smtp.c:98
util-debug.h
OutputInitResult_::ctx
OutputCtx * ctx
Definition: output.h:47
LOGGER_JSON_FILE
@ LOGGER_JSON_FILE
Definition: suricata-common.h:505
output-json.h
ALPROTO_SMTP
@ ALPROTO_SMTP
Definition: app-layer-protos.h:38
output-json-file.h
util-print.h
detect-filemagic.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
EveNFSAddMetadata
bool EveNFSAddMetadata(const Flow *f, uint64_t tx_id, SCJsonBuilder *jb)
Definition: output-json-nfs.c:61
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
pkt-var.h
EveNFSAddMetadataRPC
bool EveNFSAddMetadataRPC(const Flow *f, uint64_t tx_id, SCJsonBuilder *jb)
Definition: output-json-nfs.c:49
output-json-email-common.h
OutputInitResult_::ok
bool ok
Definition: output.h:48
LOG_DIR_FLOW
@ LOG_DIR_FLOW
Definition: output-eve-bindgen.h:35
app-layer-parser.h
SCEveJsonSimpleGetLogger
EveJsonSimpleAppLayerLogger * SCEveJsonSimpleGetLogger(AppProto alproto)
Definition: output.c:923
stream.h
JsonAddrInfo_
Definition: output-json.h:41
Packet_
Definition: decode.h:516
EveFileInfo
void EveFileInfo(SCJsonBuilder *jb, const File *ff, const uint64_t tx_id, const uint16_t flags)
Definition: output-json.c:121
conf.h
XFF_OVERWRITE
#define XFF_OVERWRITE
Definition: app-layer-htp-xff.h:33
TmEcode
TmEcode
Definition: tm-threads-common.h:80
HttpXFFCfg_
Definition: app-layer-htp-xff.h:41
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:237
EveJsonSimpleAppLayerLogger
Definition: output-eve-bindgen.h:42
AppLayerParserGetTx
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Definition: app-layer-parser.c:1219
File_::flags
uint16_t flags
Definition: util-file.h:147
SCConfNodeLookupChild
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:849
util-file.h
File_
Definition: util-file.h:146
OutputInitResult_
Definition: output.h:46
Packet_::flow
struct Flow_ * flow
Definition: decode.h:564
EveEmailAddMetadata
bool EveEmailAddMetadata(const Flow *f, uint64_t tx_id, SCJsonBuilder *js)
Definition: output-json-email-common.c:193
suricata-common.h
FileForceFilestoreEnable
void FileForceFilestoreEnable(void)
Definition: util-file.c:92
OutputCtx_::DeInit
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:94
EveJsonSimpleAppLayerLogger::LogTx
EveJsonSimpleTxLogFunc LogTx
Definition: output-eve-bindgen.h:43
JSON_ADDR_LEN
#define JSON_ADDR_LEN
Definition: output-json.h:37
output-json-nfs.h
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:36
FILE_STORED
#define FILE_STORED
Definition: util-file.h:123
JsonFileLogThread_
Definition: output-json-file.c:75
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:34
threadvars.h
util-validate.h
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
JsonAddrInfo_::src_ip
char src_ip[JSON_ADDR_LEN]
Definition: output-json.h:42
HttpXFFCfg_::flags
uint8_t flags
Definition: app-layer-htp-xff.h:42
FILE_LOGGED
#define FILE_LOGGED
Definition: util-file.h:120
SCFree
#define SCFree(p)
Definition: util-mem.h:61
util-logopenfile.h
util-buffer.h
JsonAddrInfo_::dst_ip
char dst_ip[JSON_ADDR_LEN]
Definition: output-json.h:43
JsonFileLogThread
struct JsonFileLogThread_ JsonFileLogThread
LOG_DIR_FLOW_TOCLIENT
@ LOG_DIR_FLOW_TOCLIENT
Definition: output-eve-bindgen.h:36
output-json-smb.h
ALPROTO_SMB
@ ALPROTO_SMB
Definition: app-layer-protos.h:43
OutputFileCtx_
Definition: output-json-file.c:68
HttpXFFGetIPFromTx
int HttpXFFGetIPFromTx(const Flow *f, uint64_t tx_id, HttpXFFCfg *xff_cfg, char *dstbuf, int dstbuflen)
Function to return XFF IP if any in the selected transaction. The caller needs to lock the flow.
Definition: app-layer-htp-xff.c:52
output-json-smtp.h
output-json-http.h
flow.h
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:455
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCConfNode_
Definition: conf.h:37
OutputFileCtx
struct OutputFileCtx_ OutputFileCtx
XFF_DISABLED
#define XFF_DISABLED
Definition: app-layer-htp-xff.h:29
JsonFileLogThread_::filelog_ctx
OutputFileCtx * filelog_ctx
Definition: output-json-file.c:76
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
ALPROTO_NFS
@ ALPROTO_NFS
Definition: app-layer-protos.h:51
OutputFileCtx_::file_cnt
uint32_t file_cnt
Definition: output-json-file.c:69
output.h
OutputFileCtx_::parent_xff_cfg
HttpXFFCfg * parent_xff_cfg
Definition: output-json-file.c:71