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 
172  if(initdata == NULL)
173  {
174  SCLogDebug("Error getting context. \"initdata\" argument NULL");
175  SCFree(aft);
176  return TM_ECODE_FAILED;
177  }
178 
180  if (aft->buffer == NULL) {
181  SCFree(aft);
182  return TM_ECODE_FAILED;
183  }
184 
185  /* Use the Output Context (file pointer and mutex) */
186  aft->tcpdatalog_ctx= ((OutputCtx *)initdata)->data;
187 
188  *data = (void *)aft;
189  return TM_ECODE_OK;
190 }
191 
193 {
195  if (aft == NULL) {
196  return TM_ECODE_OK;
197  }
198 
199  MemBufferFree(aft->buffer);
200  /* clear memory */
201  memset(aft, 0, sizeof(LogTcpDataLogThread));
202 
203  SCFree(aft);
204  return TM_ECODE_OK;
205 }
206 
207 /** \brief Create a new http log LogFileCtx.
208  * \param conf Pointer to ConfNode containing this loggers configuration.
209  * \return NULL if failure, LogFileCtx* to the file_ctx if succesful
210  * */
212 {
213  OutputInitResult result = { NULL, false };
214  char filename[PATH_MAX] = "";
215  char dirname[32] = "";
216  strlcpy(filename, DEFAULT_LOG_FILENAME, sizeof(filename));
217 
218  LogFileCtx *file_ctx = LogFileNewCtx();
219  if(file_ctx == NULL) {
220  SCLogError("couldn't create new file_ctx");
221  return result;
222  }
223 
224  LogTcpDataFileCtx *tcpdatalog_ctx = SCCalloc(1, sizeof(LogTcpDataFileCtx));
225  if (unlikely(tcpdatalog_ctx == NULL)) {
226  LogFileFreeCtx(file_ctx);
227  return result;
228  }
229 
230  tcpdatalog_ctx->file_ctx = file_ctx;
231 
232  if (conf) {
233  if (conf->name) {
234  if (strcmp(conf->name, "tcp-data") == 0) {
235  tcpdatalog_ctx->type = STREAMING_TCP_DATA;
236  snprintf(filename, sizeof(filename), "%s.log", conf->name);
237  strlcpy(dirname, "tcp", sizeof(dirname));
238  } else if (strcmp(conf->name, "http-body-data") == 0) {
239  tcpdatalog_ctx->type = STREAMING_HTTP_BODIES;
240  snprintf(filename, sizeof(filename), "%s.log", conf->name);
241  strlcpy(dirname, "http", sizeof(dirname));
242  }
243  }
244 
245  const char *logtype = ConfNodeLookupChildValue(conf, "type");
246  if (logtype == NULL)
247  logtype = "file";
248 
249  if (strcmp(logtype, "file") == 0) {
250  tcpdatalog_ctx->file = 1;
251  } else if (strcmp(logtype, "dir") == 0) {
252  tcpdatalog_ctx->dir = 1;
253  } else if (strcmp(logtype, "both") == 0) {
254  tcpdatalog_ctx->file = 1;
255  tcpdatalog_ctx->dir = 1;
256  }
257  } else {
258  tcpdatalog_ctx->file = 1;
259  tcpdatalog_ctx->dir = 0;
260  }
261 
262  if (tcpdatalog_ctx->file == 1) {
263  SCLogInfo("opening logfile");
264  if (SCConfLogOpenGeneric(conf, file_ctx, filename, 1) < 0) {
265  LogFileFreeCtx(file_ctx);
266  SCFree(tcpdatalog_ctx);
267  return result;
268  }
269  }
270 
271  if (tcpdatalog_ctx->dir == 1) {
272  tcpdatalog_ctx->log_dir = ConfigGetLogDirectory();
273  char dirfull[PATH_MAX];
274 
275  /* create the filename to use */
276  snprintf(dirfull, PATH_MAX, "%s/%s", tcpdatalog_ctx->log_dir, dirname);
277 
278  SCLogInfo("using directory %s", dirfull);
279 
280  /* if mkdir fails file open will fail, so deal with errors there */
281  (void)SCMkDir(dirfull, 0700);
282  }
283 
284  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
285  if (unlikely(output_ctx == NULL)) {
286  goto parsererror;
287  }
288 
289  output_ctx->data = tcpdatalog_ctx;
290  output_ctx->DeInit = LogTcpDataLogDeInitCtx;
291 
292  SCLogDebug("Streaming log output initialized");
293  result.ctx = output_ctx;
294  result.ok = true;
295  return result;
296 
297 parsererror:
298  LogFileFreeCtx(file_ctx);
299  SCFree(tcpdatalog_ctx);
300  SCLogError("Syntax error in custom http log format string.");
301  return result;
302 
303 }
304 
305 static void LogTcpDataLogDeInitCtx(OutputCtx *output_ctx)
306 {
307  LogTcpDataFileCtx *tcpdatalog_ctx = (LogTcpDataFileCtx *)output_ctx->data;
308  LogFileFreeCtx(tcpdatalog_ctx->file_ctx);
309  SCFree(tcpdatalog_ctx);
310  SCFree(output_ctx);
311 }
LogTcpDataLogThread_
Definition: log-tcp-data.c:63
FLOW_IS_IPV6
#define FLOW_IS_IPV6(f)
Definition: flow.h:171
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:659
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:360
LogFileCtx_
Definition: util-logopenfile.h:72
LogFileCtx_::Write
int(* Write)(const char *buffer, int buffer_len, struct LogFileCtx_ *fp)
Definition: util-logopenfile.h:87
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:543
Flow_::dp
Port dp
Definition: flow.h:376
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: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:88
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:84
OutputCtx_
Definition: tm-modules.h:85
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:452
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
Flow_::dst
FlowAddress dst
Definition: flow.h:363
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:485
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:231
OutputInitResult_::ok
bool ok
Definition: output.h:48
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
FLOW_IS_IPV4
#define FLOW_IS_IPV4(f)
Definition: flow.h:169
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:363
OutputInitResult_
Definition: output.h:46
util-conf.h
LogTcpDataLogInitCtx
OutputInitResult LogTcpDataLogInitCtx(ConfNode *conf)
Create a new http log LogFileCtx.
Definition: log-tcp-data.c:211
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:91
util-path.h
STREAMING_HTTP_BODIES
@ STREAMING_HTTP_BODIES
Definition: output-streaming.h:37
LogTcpDataLogThread_::tcpdatalog_ctx
LogTcpDataFileCtx * tcpdatalog_ctx
Definition: log-tcp-data.c:64
MemBufferFree
void MemBufferFree(MemBuffer *buffer)
Definition: util-buffer.c:81
ConfNode_::name
char * name
Definition: conf.h:33
LogFileFreeCtx
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
Definition: util-logopenfile.c:868
SCMkDir
#define SCMkDir(a, b)
Definition: util-path.h:45
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
threadvars.h
LogTcpDataLogThread_::buffer
MemBuffer * buffer
Definition: log-tcp-data.c:66
ConfigGetLogDirectory
const char * ConfigGetLogDirectory(void)
Definition: util-conf.c:38
OutputStreamingType
OutputStreamingType
Definition: output-streaming.h:35
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: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:192
LogTcpDataFileCtx_::file
int file
Definition: log-tcp-data.c:59
MemBufferWriteString
void MemBufferWriteString(MemBuffer *dst, const char *fmt,...)
Definition: util-buffer.c:125
PrintRawUriBuf
void PrintRawUriBuf(char *retbuf, uint32_t *offset, uint32_t retbuflen, uint8_t *buf, uint32_t buflen)
Definition: util-print.c:93
MemBuffer_::size
uint32_t size
Definition: util-buffer.h:28
STREAMING_TCP_DATA
@ STREAMING_TCP_DATA
Definition: output-streaming.h:36
MEMBUFFER_BUFFER
#define MEMBUFFER_BUFFER(mem_buffer)
Get the MemBuffers underlying buffer.
Definition: util-buffer.h:51
Flow_::sp
Port sp
Definition: flow.h:365
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: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:809