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  PrintInet(AF_INET6, (const void *)f->src.addr_data32, srcip, sizeof(srcip));
87  PrintInet(AF_INET6, (const void *)f->dst.addr_data32, dstip, sizeof(dstip));
88  }
89 
90  char name[PATH_MAX];
91 
92  char tx[64] = { 0 };
94  snprintf(tx, sizeof(tx), "%"PRIu64, tx_id);
95  }
96 
97  snprintf(name, sizeof(name), "%s/%s/%s_%u-%s_%u-%s-%s.data",
98  td->log_dir,
99  td->type == STREAMING_HTTP_BODIES ? "http" : "tcp",
100  srcip, f->sp, dstip, f->dp, tx,
101  flags & OUTPUT_STREAMING_FLAG_TOSERVER ? "ts" : "tc");
102 
103  FILE *fp = fopen(name, mode);
104  BUG_ON(fp == NULL);
105 
106  // PrintRawDataFp(stdout, (uint8_t *)data, data_len);
107  fwrite(data, data_len, 1, fp);
108 
109  fclose(fp);
110  }
112 }
113 
114 static int LogTcpDataLoggerFile(ThreadVars *tv, void *thread_data, const Flow *f,
115  const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
116 {
117  SCEnter();
118  LogTcpDataLogThread *aft = thread_data;
120 
121  if (data && data_len) {
122  MemBufferReset(aft->buffer);
123 
124  char srcip[46] = "", dstip[46] = "";
125  if (FLOW_IS_IPV4(f)) {
126  PrintInet(AF_INET, (const void *)&f->src.addr_data32[0], srcip, sizeof(srcip));
127  PrintInet(AF_INET, (const void *)&f->dst.addr_data32[0], dstip, sizeof(dstip));
128  } else if (FLOW_IS_IPV6(f)) {
129  PrintInet(AF_INET6, (const void *)f->src.addr_data32, srcip, sizeof(srcip));
130  PrintInet(AF_INET6, (const void *)f->dst.addr_data32, dstip, sizeof(dstip));
131  }
132 
133  char name[PATH_MAX];
134  snprintf(name, sizeof(name), "%s_%u-%s_%u-%s:",
135  srcip, f->sp, dstip, f->dp,
136  flags & OUTPUT_STREAMING_FLAG_TOSERVER ? "ts" : "tc");
137 
138  PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
139  aft->buffer->size, (uint8_t *)name,strlen(name));
140  MemBufferWriteString(aft->buffer, "\n");
141 
143  aft->buffer->size, (uint8_t *)data,data_len);
144 
145  td->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer),
146  MEMBUFFER_OFFSET(aft->buffer), td->file_ctx);
147  }
149 }
150 
151 int LogTcpDataLogger(ThreadVars *tv, void *thread_data, const Flow *f,
152  const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
153 {
154  SCEnter();
155  LogTcpDataLogThread *aft = thread_data;
157 
158  if (td->dir == 1)
159  LogTcpDataLoggerDir(tv, thread_data, f, data, data_len, tx_id, flags);
160  if (td->file == 1)
161  LogTcpDataLoggerFile(tv, thread_data, f, data, data_len, tx_id, flags);
162 
164 }
165 
166 TmEcode LogTcpDataLogThreadInit(ThreadVars *t, const void *initdata, void **data)
167 {
169  if (unlikely(aft == NULL))
170  return TM_ECODE_FAILED;
171  memset(aft, 0, sizeof(LogTcpDataLogThread));
172 
173  if(initdata == NULL)
174  {
175  SCLogDebug("Error getting context. \"initdata\" argument NULL");
176  SCFree(aft);
177  return TM_ECODE_FAILED;
178  }
179 
181  if (aft->buffer == NULL) {
182  SCFree(aft);
183  return TM_ECODE_FAILED;
184  }
185 
186  /* Use the Output Context (file pointer and mutex) */
187  aft->tcpdatalog_ctx= ((OutputCtx *)initdata)->data;
188 
189  *data = (void *)aft;
190  return TM_ECODE_OK;
191 }
192 
194 {
196  if (aft == NULL) {
197  return TM_ECODE_OK;
198  }
199 
200  MemBufferFree(aft->buffer);
201  /* clear memory */
202  memset(aft, 0, sizeof(LogTcpDataLogThread));
203 
204  SCFree(aft);
205  return TM_ECODE_OK;
206 }
207 
208 /** \brief Create a new http log LogFileCtx.
209  * \param conf Pointer to ConfNode containing this loggers configuration.
210  * \return NULL if failure, LogFileCtx* to the file_ctx if succesful
211  * */
213 {
214  OutputInitResult result = { NULL, false };
215  char filename[PATH_MAX] = "";
216  char dirname[32] = "";
217  strlcpy(filename, DEFAULT_LOG_FILENAME, sizeof(filename));
218 
219  LogFileCtx *file_ctx = LogFileNewCtx();
220  if(file_ctx == NULL) {
221  SCLogError("couldn't create new file_ctx");
222  return result;
223  }
224 
225  LogTcpDataFileCtx *tcpdatalog_ctx = SCMalloc(sizeof(LogTcpDataFileCtx));
226  if (unlikely(tcpdatalog_ctx == NULL)) {
227  LogFileFreeCtx(file_ctx);
228  return result;
229  }
230  memset(tcpdatalog_ctx, 0x00, sizeof(LogTcpDataFileCtx));
231 
232  tcpdatalog_ctx->file_ctx = file_ctx;
233 
234  if (conf) {
235  if (conf->name) {
236  if (strcmp(conf->name, "tcp-data") == 0) {
237  tcpdatalog_ctx->type = STREAMING_TCP_DATA;
238  snprintf(filename, sizeof(filename), "%s.log", conf->name);
239  strlcpy(dirname, "tcp", sizeof(dirname));
240  } else if (strcmp(conf->name, "http-body-data") == 0) {
241  tcpdatalog_ctx->type = STREAMING_HTTP_BODIES;
242  snprintf(filename, sizeof(filename), "%s.log", conf->name);
243  strlcpy(dirname, "http", sizeof(dirname));
244  }
245  }
246 
247  const char *logtype = ConfNodeLookupChildValue(conf, "type");
248  if (logtype == NULL)
249  logtype = "file";
250 
251  if (strcmp(logtype, "file") == 0) {
252  tcpdatalog_ctx->file = 1;
253  } else if (strcmp(logtype, "dir") == 0) {
254  tcpdatalog_ctx->dir = 1;
255  } else if (strcmp(logtype, "both") == 0) {
256  tcpdatalog_ctx->file = 1;
257  tcpdatalog_ctx->dir = 1;
258  }
259  } else {
260  tcpdatalog_ctx->file = 1;
261  tcpdatalog_ctx->dir = 0;
262  }
263 
264  if (tcpdatalog_ctx->file == 1) {
265  SCLogInfo("opening logfile");
266  if (SCConfLogOpenGeneric(conf, file_ctx, filename, 1) < 0) {
267  LogFileFreeCtx(file_ctx);
268  SCFree(tcpdatalog_ctx);
269  return result;
270  }
271  }
272 
273  if (tcpdatalog_ctx->dir == 1) {
274  tcpdatalog_ctx->log_dir = ConfigGetLogDirectory();
275  char dirfull[PATH_MAX];
276 
277  /* create the filename to use */
278  snprintf(dirfull, PATH_MAX, "%s/%s", tcpdatalog_ctx->log_dir, dirname);
279 
280  SCLogInfo("using directory %s", dirfull);
281 
282  /* if mkdir fails file open will fail, so deal with errors there */
283  (void)SCMkDir(dirfull, 0700);
284  }
285 
286  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
287  if (unlikely(output_ctx == NULL)) {
288  goto parsererror;
289  }
290 
291  output_ctx->data = tcpdatalog_ctx;
292  output_ctx->DeInit = LogTcpDataLogDeInitCtx;
293 
294  SCLogDebug("Streaming log output initialized");
295  result.ctx = output_ctx;
296  result.ok = true;
297  return result;
298 
299 parsererror:
300  LogFileFreeCtx(file_ctx);
301  SCFree(tcpdatalog_ctx);
302  SCLogError("Syntax error in custom http log format string.");
303  return result;
304 
305 }
306 
307 static void LogTcpDataLogDeInitCtx(OutputCtx *output_ctx)
308 {
309  LogTcpDataFileCtx *tcpdatalog_ctx = (LogTcpDataFileCtx *)output_ctx->data;
310  LogFileFreeCtx(tcpdatalog_ctx->file_ctx);
311  SCFree(tcpdatalog_ctx);
312  SCFree(output_ctx);
313 }
LogTcpDataLogThread_
Definition: log-tcp-data.c:63
FLOW_IS_IPV6
#define FLOW_IS_IPV6(f)
Definition: flow.h:161
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:660
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
OUTPUT_BUFFER_SIZE
#define OUTPUT_BUFFER_SIZE
Definition: log-tcp-data.c:38
Flow_
Flow data structure.
Definition: flow.h:343
LogFileCtx_
Definition: util-logopenfile.h:72
LogFileCtx_::Write
int(* Write)(const char *buffer, int buffer_len, struct LogFileCtx_ *fp)
Definition: util-logopenfile.h:88
OutputRegisterStreamingModule
void OutputRegisterStreamingModule(LoggerId id, const char *name, const char *conf_name, OutputInitFunc InitFunc, StreamingLogger StreamingLogFunc, enum OutputStreamingType stream_type, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit, ThreadExitPrintStatsFunc ThreadExitPrintStats)
Register a streaming data output module.
Definition: output.c:627
Flow_::dp
Port dp
Definition: flow.h:359
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:85
LogTcpDataLogThreadInit
TmEcode LogTcpDataLogThreadInit(ThreadVars *, const void *, void **)
Definition: log-tcp-data.c:166
OUTPUT_STREAMING_FLAG_TRANSACTION
#define OUTPUT_STREAMING_FLAG_TRANSACTION
Definition: output-streaming.h:34
LogTcpDataLogRegister
void LogTcpDataLogRegister(void)
Definition: log-tcp-data.c:46
MemBuffer_::offset
uint32_t offset
Definition: util-buffer.h:30
OutputCtx_::data
void * data
Definition: tm-modules.h:87
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:84
OutputCtx_
Definition: tm-modules.h:84
SCConfLogOpenGeneric
int SCConfLogOpenGeneric(ConfNode *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:453
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
Flow_::dst
FlowAddress dst
Definition: flow.h:346
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:181
log-tcp-data.h
LOGGER_TCP_DATA
@ LOGGER_TCP_DATA
Definition: suricata-common.h:479
OutputInitResult_::ctx
OutputCtx * ctx
Definition: output.h:47
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
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:151
PrintInet
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:274
OutputInitResult_::ok
bool ok
Definition: output.h:48
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:295
FLOW_IS_IPV4
#define FLOW_IS_IPV4(f)
Definition: flow.h:159
TmEcode
TmEcode
Definition: tm-threads-common.h:83
LogTcpDataFileCtx_::dir
int dir
Definition: log-tcp-data.c:60
MemBuffer_
Definition: util-buffer.h:27
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:224
Flow_::src
FlowAddress src
Definition: flow.h:346
MemBufferReset
#define MemBufferReset(mem_buffer)
Reset the mem buffer.
Definition: util-buffer.h:42
OutputInitResult_
Definition: output.h:46
util-conf.h
LogTcpDataLogInitCtx
OutputInitResult LogTcpDataLogInitCtx(ConfNode *conf)
Create a new http log LogFileCtx.
Definition: log-tcp-data.c:212
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:30
OutputCtx_::DeInit
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:90
util-path.h
STREAMING_HTTP_BODIES
@ STREAMING_HTTP_BODIES
Definition: output-streaming.h:38
LogTcpDataLogThread_::tcpdatalog_ctx
LogTcpDataFileCtx * tcpdatalog_ctx
Definition: log-tcp-data.c:64
MemBufferFree
void MemBufferFree(MemBuffer *buffer)
Definition: util-buffer.c:87
ConfNode_::name
char * name
Definition: conf.h:33
MemBufferWriteString
#define MemBufferWriteString(dst,...)
Write a string buffer to the Membuffer dst.
Definition: util-buffer.h:162
LogFileFreeCtx
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
Definition: util-logopenfile.c:862
SCMkDir
#define SCMkDir(a, b)
Definition: util-path.h:29
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
threadvars.h
LogTcpDataLogThread_::buffer
MemBuffer * buffer
Definition: log-tcp-data.c:66
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
ConfigGetLogDirectory
const char * ConfigGetLogDirectory(void)
Definition: util-conf.c:37
OutputStreamingType
OutputStreamingType
Definition: output-streaming.h:36
OUTPUT_STREAMING_FLAG_TOSERVER
#define OUTPUT_STREAMING_FLAG_TOSERVER
Definition: output-streaming.h:32
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
ConfNode_
Definition: conf.h:32
util-logopenfile.h
LogTcpDataFileCtx
struct LogTcpDataFileCtx_ LogTcpDataFileCtx
LogTcpDataLogThreadDeinit
TmEcode LogTcpDataLogThreadDeinit(ThreadVars *, void *)
Definition: log-tcp-data.c:193
LogTcpDataFileCtx_::file
int file
Definition: log-tcp-data.c:59
PrintRawUriBuf
void PrintRawUriBuf(char *retbuf, uint32_t *offset, uint32_t retbuflen, uint8_t *buf, uint32_t buflen)
Definition: util-print.c:120
MemBuffer_::size
uint32_t size
Definition: util-buffer.h:29
STREAMING_TCP_DATA
@ STREAMING_TCP_DATA
Definition: output-streaming.h:37
MEMBUFFER_BUFFER
#define MEMBUFFER_BUFFER(mem_buffer)
Get the MemBuffers underlying buffer.
Definition: util-buffer.h:50
Flow_::sp
Port sp
Definition: flow.h:348
MemBuffer_::buffer
uint8_t * buffer
Definition: util-buffer.h:28
MEMBUFFER_OFFSET
#define MEMBUFFER_OFFSET(mem_buffer)
Get the MemBuffers current offset.
Definition: util-buffer.h:55
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
MemBufferCreateNew
MemBuffer * MemBufferCreateNew(uint32_t size)
Definition: util-buffer.c:32
LogTcpDataFileCtx_::type
enum OutputStreamingType type
Definition: log-tcp-data.c:57
LogTcpDataLogThread
struct LogTcpDataLogThread_ LogTcpDataLogThread
ConfNodeLookupChildValue
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:812