suricata
log-tcp-data.c
Go to the documentation of this file.
1 /* Copyright (C) 2014 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 Victor Julien <victor@inliniac.net>
22  */
23 
24 #include "suricata-common.h"
25 #include "log-tcp-data.h"
26 
27 #include "threadvars.h"
28 
29 #include "util-conf.h"
30 #include "util-logopenfile.h"
31 #include "util-path.h"
32 #include "util-print.h"
33 
34 #define DEFAULT_LOG_FILENAME "tcp-data.log"
35 
36 #define MODULE_NAME "LogTcpDataLog"
37 
38 #define OUTPUT_BUFFER_SIZE 65535
39 
40 TmEcode LogTcpDataLogThreadInit(ThreadVars *, const void *, void **);
42 static void LogTcpDataLogDeInitCtx(OutputCtx *);
43 
44 int LogTcpDataLogger(ThreadVars *tv, void *thread_data, const Flow *f, const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags);
45 
46 void LogTcpDataLogRegister (void) {
53 }
54 
55 typedef struct LogTcpDataFileCtx_ {
58  const char *log_dir;
59  int file;
60  int dir;
62 
63 typedef struct LogTcpDataLogThread_ {
65  /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
68 
69 static int LogTcpDataLoggerDir(ThreadVars *tv, void *thread_data, const Flow *f,
70  const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
71 {
72  SCEnter();
73  LogTcpDataLogThread *aft = thread_data;
75  const char *mode = "a";
76 
78  mode = "w";
79 
80  if (data && data_len) {
81  char srcip[46] = "", dstip[46] = "";
82  if (FLOW_IS_IPV4(f)) {
83  PrintInet(AF_INET, (const void *)&f->src.addr_data32[0], srcip, sizeof(srcip));
84  PrintInet(AF_INET, (const void *)&f->dst.addr_data32[0], dstip, sizeof(dstip));
85  } else if (FLOW_IS_IPV6(f)) {
86  PrintInetIPv6((const void *)f->src.addr_data32, srcip, sizeof(srcip),
87  td->file_ctx->compress_ipv6);
88  PrintInetIPv6((const void *)f->dst.addr_data32, dstip, sizeof(dstip),
89  td->file_ctx->compress_ipv6);
90  }
91 
92  char name[PATH_MAX];
93 
94  char tx[64] = { 0 };
96  snprintf(tx, sizeof(tx), "%"PRIu64, tx_id);
97  }
98 
99  snprintf(name, sizeof(name), "%s/%s/%s_%u-%s_%u-%s-%s.data",
100  td->log_dir,
101  td->type == STREAMING_HTTP_BODIES ? "http" : "tcp",
102  srcip, f->sp, dstip, f->dp, tx,
103  flags & OUTPUT_STREAMING_FLAG_TOSERVER ? "ts" : "tc");
104 
105  FILE *fp = fopen(name, mode);
106  BUG_ON(fp == NULL);
107 
108  // PrintRawDataFp(stdout, (uint8_t *)data, data_len);
109  fwrite(data, data_len, 1, fp);
110 
111  fclose(fp);
112  }
114 }
115 
116 static int LogTcpDataLoggerFile(ThreadVars *tv, void *thread_data, const Flow *f,
117  const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
118 {
119  SCEnter();
120  LogTcpDataLogThread *aft = thread_data;
122 
123  if (data && data_len) {
124  MemBufferReset(aft->buffer);
125 
126  char srcip[46] = "", dstip[46] = "";
127  if (FLOW_IS_IPV4(f)) {
128  PrintInet(AF_INET, (const void *)&f->src.addr_data32[0], srcip, sizeof(srcip));
129  PrintInet(AF_INET, (const void *)&f->dst.addr_data32[0], dstip, sizeof(dstip));
130  } else if (FLOW_IS_IPV6(f)) {
131  PrintInetIPv6((const void *)f->src.addr_data32, srcip, sizeof(srcip),
132  td->file_ctx->compress_ipv6);
133  PrintInetIPv6((const void *)f->dst.addr_data32, dstip, sizeof(dstip),
134  td->file_ctx->compress_ipv6);
135  }
136 
137  char name[PATH_MAX];
138  snprintf(name, sizeof(name), "%s_%u-%s_%u-%s:",
139  srcip, f->sp, dstip, f->dp,
140  flags & OUTPUT_STREAMING_FLAG_TOSERVER ? "ts" : "tc");
141 
142  PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
143  aft->buffer->size, (uint8_t *)name,strlen(name));
144  MemBufferWriteString(aft->buffer, "\n");
145 
147  aft->buffer->size, (uint8_t *)data,data_len);
148 
149  td->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer),
150  MEMBUFFER_OFFSET(aft->buffer), td->file_ctx);
151  }
153 }
154 
155 int LogTcpDataLogger(ThreadVars *tv, void *thread_data, const Flow *f,
156  const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
157 {
158  SCEnter();
159  LogTcpDataLogThread *aft = thread_data;
161 
162  if (td->dir == 1)
163  LogTcpDataLoggerDir(tv, thread_data, f, data, data_len, tx_id, flags);
164  if (td->file == 1)
165  LogTcpDataLoggerFile(tv, thread_data, f, data, data_len, tx_id, flags);
166 
168 }
169 
170 TmEcode LogTcpDataLogThreadInit(ThreadVars *t, const void *initdata, void **data)
171 {
173  if (unlikely(aft == NULL))
174  return TM_ECODE_FAILED;
175 
176  if(initdata == NULL)
177  {
178  SCLogDebug("Error getting context. \"initdata\" argument NULL");
179  SCFree(aft);
180  return TM_ECODE_FAILED;
181  }
182 
184  if (aft->buffer == NULL) {
185  SCFree(aft);
186  return TM_ECODE_FAILED;
187  }
188 
189  /* Use the Output Context (file pointer and mutex) */
190  aft->tcpdatalog_ctx= ((OutputCtx *)initdata)->data;
191 
192  *data = (void *)aft;
193  return TM_ECODE_OK;
194 }
195 
197 {
199  if (aft == NULL) {
200  return TM_ECODE_OK;
201  }
202 
203  MemBufferFree(aft->buffer);
204  /* clear memory */
205  memset(aft, 0, sizeof(LogTcpDataLogThread));
206 
207  SCFree(aft);
208  return TM_ECODE_OK;
209 }
210 
211 /** \brief Create a new http log LogFileCtx.
212  * \param conf Pointer to ConfNode containing this loggers configuration.
213  * \return NULL if failure, LogFileCtx* to the file_ctx if succesful
214  * */
216 {
217  OutputInitResult result = { NULL, false };
218  char filename[PATH_MAX] = "";
219  char dirname[32] = "";
220  strlcpy(filename, DEFAULT_LOG_FILENAME, sizeof(filename));
221 
222  LogFileCtx *file_ctx = LogFileNewCtx();
223  if(file_ctx == NULL) {
224  SCLogError("couldn't create new file_ctx");
225  return result;
226  }
227 
228  LogTcpDataFileCtx *tcpdatalog_ctx = SCCalloc(1, sizeof(LogTcpDataFileCtx));
229  if (unlikely(tcpdatalog_ctx == NULL)) {
230  LogFileFreeCtx(file_ctx);
231  return result;
232  }
233 
234  tcpdatalog_ctx->file_ctx = file_ctx;
235 
236  if (conf) {
237  if (conf->name) {
238  if (strcmp(conf->name, "tcp-data") == 0) {
239  tcpdatalog_ctx->type = STREAMING_TCP_DATA;
240  snprintf(filename, sizeof(filename), "%s.log", conf->name);
241  strlcpy(dirname, "tcp", sizeof(dirname));
242  } else if (strcmp(conf->name, "http-body-data") == 0) {
243  tcpdatalog_ctx->type = STREAMING_HTTP_BODIES;
244  snprintf(filename, sizeof(filename), "%s.log", conf->name);
245  strlcpy(dirname, "http", sizeof(dirname));
246  }
247  }
248 
249  const char *logtype = SCConfNodeLookupChildValue(conf, "type");
250  if (logtype == NULL)
251  logtype = "file";
252 
253  if (strcmp(logtype, "file") == 0) {
254  tcpdatalog_ctx->file = 1;
255  } else if (strcmp(logtype, "dir") == 0) {
256  tcpdatalog_ctx->dir = 1;
257  } else if (strcmp(logtype, "both") == 0) {
258  tcpdatalog_ctx->file = 1;
259  tcpdatalog_ctx->dir = 1;
260  }
261  } else {
262  tcpdatalog_ctx->file = 1;
263  tcpdatalog_ctx->dir = 0;
264  }
265 
266  if (tcpdatalog_ctx->file == 1) {
267  SCLogInfo("opening logfile");
268  if (SCConfLogOpenGeneric(conf, file_ctx, filename, 1) < 0) {
269  LogFileFreeCtx(file_ctx);
270  SCFree(tcpdatalog_ctx);
271  return result;
272  }
273  }
274 
275  if (tcpdatalog_ctx->dir == 1) {
276  tcpdatalog_ctx->log_dir = SCConfigGetLogDirectory();
277  char dirfull[PATH_MAX];
278 
279  /* create the filename to use */
280  snprintf(dirfull, PATH_MAX, "%s/%s", tcpdatalog_ctx->log_dir, dirname);
281 
282  SCLogInfo("using directory %s", dirfull);
283 
284  /* if mkdir fails file open will fail, so deal with errors there */
285  (void)SCMkDir(dirfull, 0700);
286  }
287 
288  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
289  if (unlikely(output_ctx == NULL)) {
290  goto parsererror;
291  }
292 
293  output_ctx->data = tcpdatalog_ctx;
294  output_ctx->DeInit = LogTcpDataLogDeInitCtx;
295 
296  SCLogDebug("Streaming log output initialized");
297  result.ctx = output_ctx;
298  result.ok = true;
299  return result;
300 
301 parsererror:
302  LogFileFreeCtx(file_ctx);
303  SCFree(tcpdatalog_ctx);
304  SCLogError("Syntax error in custom http log format string.");
305  return result;
306 
307 }
308 
309 static void LogTcpDataLogDeInitCtx(OutputCtx *output_ctx)
310 {
311  LogTcpDataFileCtx *tcpdatalog_ctx = (LogTcpDataFileCtx *)output_ctx->data;
312  LogFileFreeCtx(tcpdatalog_ctx->file_ctx);
313  SCFree(tcpdatalog_ctx);
314  SCFree(output_ctx);
315 }
LogTcpDataLogThread_
Definition: log-tcp-data.c:63
OutputRegisterStreamingModule
void OutputRegisterStreamingModule(LoggerId id, const char *name, const char *conf_name, OutputInitFunc InitFunc, SCStreamingLogger StreamingLogFunc, enum SCOutputStreamingType stream_type, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit)
Register a streaming data output module.
Definition: output.c:531
STREAMING_TCP_DATA
@ STREAMING_TCP_DATA
Definition: output-streaming.h:36
FLOW_IS_IPV6
#define FLOW_IS_IPV6(f)
Definition: flow.h:163
MemBuffer_::buffer
uint8_t buffer[]
Definition: util-buffer.h:30
MODULE_NAME
#define MODULE_NAME
Definition: log-tcp-data.c:36
DEFAULT_LOG_FILENAME
#define DEFAULT_LOG_FILENAME
Definition: log-tcp-data.c:34
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
LogFileNewCtx
LogFileCtx * LogFileNewCtx(void)
LogFileNewCtx() Get a new LogFileCtx.
Definition: util-logopenfile.c:712
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
OUTPUT_BUFFER_SIZE
#define OUTPUT_BUFFER_SIZE
Definition: log-tcp-data.c:38
name
const char * name
Definition: detect-engine-proto.c:48
LogTcpDataFileCtx_::type
enum SCOutputStreamingType type
Definition: log-tcp-data.c:57
LogTcpDataLogInitCtx
OutputInitResult LogTcpDataLogInitCtx(SCConfNode *conf)
Create a new http log LogFileCtx.
Definition: log-tcp-data.c:215
PrintInetIPv6
const char * PrintInetIPv6(const void *src, char *dst, socklen_t size, bool compress_ipv6)
Definition: util-print.c:209
Flow_
Flow data structure.
Definition: flow.h:347
PrintRawUriBuf
void PrintRawUriBuf(char *retbuf, uint32_t *offset, uint32_t retbuflen, const uint8_t *buf, size_t buflen)
Definition: util-print.c:93
LogFileCtx_
Definition: util-logopenfile.h:72
LogFileCtx_::Write
int(* Write)(const char *buffer, int buffer_len, struct LogFileCtx_ *fp)
Definition: util-logopenfile.h:87
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:855
Flow_::dp
Port dp
Definition: flow.h:363
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
LogTcpDataLogThreadInit
TmEcode LogTcpDataLogThreadInit(ThreadVars *, const void *, void **)
Definition: log-tcp-data.c:170
OUTPUT_STREAMING_FLAG_TRANSACTION
#define OUTPUT_STREAMING_FLAG_TRANSACTION
Definition: output-streaming.h:33
LogTcpDataLogRegister
void LogTcpDataLogRegister(void)
Definition: log-tcp-data.c:46
MemBuffer_::offset
uint32_t offset
Definition: util-buffer.h:29
OutputCtx_::data
void * data
Definition: tm-modules.h:91
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
OutputCtx_
Definition: tm-modules.h:88
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
Flow_::dst
FlowAddress dst
Definition: flow.h:350
LogTcpDataFileCtx_::file_ctx
LogFileCtx * file_ctx
Definition: log-tcp-data.c:56
LogTcpDataFileCtx_::log_dir
const char * log_dir
Definition: log-tcp-data.c:58
PrintRawDataToBuffer
void PrintRawDataToBuffer(uint8_t *dst_buf, uint32_t *dst_buf_offset_ptr, uint32_t dst_buf_size, const uint8_t *src_buf, uint32_t src_buf_len)
Definition: util-print.c:149
log-tcp-data.h
LOGGER_TCP_DATA
@ LOGGER_TCP_DATA
Definition: suricata-common.h:502
OutputInitResult_::ctx
OutputCtx * ctx
Definition: output.h:47
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
LogTcpDataFileCtx_
Definition: log-tcp-data.c:55
LogTcpDataLogger
int LogTcpDataLogger(ThreadVars *tv, void *thread_data, const Flow *f, const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
Definition: log-tcp-data.c:155
PrintInet
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:238
OutputInitResult_::ok
bool ok
Definition: output.h:48
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
FLOW_IS_IPV4
#define FLOW_IS_IPV4(f)
Definition: flow.h:161
SCConfigGetLogDirectory
const char * SCConfigGetLogDirectory(void)
Definition: util-conf.c:38
TmEcode
TmEcode
Definition: tm-threads-common.h:80
LogTcpDataFileCtx_::dir
int dir
Definition: log-tcp-data.c:60
LogFileCtx_::compress_ipv6
bool compress_ipv6
Definition: util-logopenfile.h:150
MemBuffer_
Definition: util-buffer.h:27
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:232
Flow_::src
FlowAddress src
Definition: flow.h:350
OutputInitResult_
Definition: output.h:46
util-conf.h
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
OUTPUT_STREAMING_FLAG_OPEN
#define OUTPUT_STREAMING_FLAG_OPEN
Definition: output-streaming.h:29
OutputCtx_::DeInit
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:94
util-path.h
LogTcpDataLogThread_::tcpdatalog_ctx
LogTcpDataFileCtx * tcpdatalog_ctx
Definition: log-tcp-data.c:64
MemBufferFree
void MemBufferFree(MemBuffer *buffer)
Definition: util-buffer.c:86
LogFileFreeCtx
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
Definition: util-logopenfile.c:926
SCMkDir
#define SCMkDir(a, b)
Definition: util-path.h:45
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:33
threadvars.h
LogTcpDataLogThread_::buffer
MemBuffer * buffer
Definition: log-tcp-data.c:66
OUTPUT_STREAMING_FLAG_TOSERVER
#define OUTPUT_STREAMING_FLAG_TOSERVER
Definition: output-streaming.h:31
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SCConfLogOpenGeneric
int SCConfLogOpenGeneric(SCConfNode *conf, LogFileCtx *log_ctx, const char *default_filename, int rotate)
open a generic output "log file", which may be a regular file or a socket
Definition: util-logopenfile.c:480
SCFree
#define SCFree(p)
Definition: util-mem.h:61
util-logopenfile.h
LogTcpDataFileCtx
struct LogTcpDataFileCtx_ LogTcpDataFileCtx
STREAMING_HTTP_BODIES
@ STREAMING_HTTP_BODIES
Definition: output-streaming.h:37
LogTcpDataLogThreadDeinit
TmEcode LogTcpDataLogThreadDeinit(ThreadVars *, void *)
Definition: log-tcp-data.c:196
LogTcpDataFileCtx_::file
int file
Definition: log-tcp-data.c:59
MemBufferWriteString
void MemBufferWriteString(MemBuffer *dst, const char *fmt,...)
Definition: util-buffer.c:130
SCConfNode_::name
char * name
Definition: conf.h:38
MemBuffer_::size
uint32_t size
Definition: util-buffer.h:28
SCOutputStreamingType
SCOutputStreamingType
Definition: output-streaming.h:35
MEMBUFFER_BUFFER
#define MEMBUFFER_BUFFER(mem_buffer)
Get the MemBuffers underlying buffer.
Definition: util-buffer.h:51
Flow_::sp
Port sp
Definition: flow.h:352
MEMBUFFER_OFFSET
#define MEMBUFFER_OFFSET(mem_buffer)
Get the MemBuffers current offset.
Definition: util-buffer.h:56
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
SCConfNode_
Definition: conf.h:37
MemBufferCreateNew
MemBuffer * MemBufferCreateNew(uint32_t size)
Definition: util-buffer.c:32
LogTcpDataLogThread
struct LogTcpDataLogThread_ LogTcpDataLogThread