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  if (fp == NULL) {
107  SCLogWarning("failed to open '%s': %s", name, strerror(errno));
109  }
110 
111  // PrintRawDataFp(stdout, (uint8_t *)data, data_len);
112  if (fwrite(data, data_len, 1, fp) != 1) {
113  SCLogWarning("write to '%s' failed: %s", name, strerror(errno));
114  }
115 
116  if (fclose(fp) != 0) {
117  SCLogWarning("failed to close '%s': %s", name, strerror(errno));
118  }
119  }
121 }
122 
123 static int LogTcpDataLoggerFile(ThreadVars *tv, void *thread_data, const Flow *f,
124  const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
125 {
126  SCEnter();
127  LogTcpDataLogThread *aft = thread_data;
129 
130  if (data && data_len) {
131  MemBufferReset(aft->buffer);
132 
133  char srcip[46] = "", dstip[46] = "";
134  if (FLOW_IS_IPV4(f)) {
135  PrintInet(AF_INET, (const void *)&f->src.addr_data32[0], srcip, sizeof(srcip));
136  PrintInet(AF_INET, (const void *)&f->dst.addr_data32[0], dstip, sizeof(dstip));
137  } else if (FLOW_IS_IPV6(f)) {
138  PrintInetIPv6((const void *)f->src.addr_data32, srcip, sizeof(srcip),
139  td->file_ctx->compress_ipv6);
140  PrintInetIPv6((const void *)f->dst.addr_data32, dstip, sizeof(dstip),
141  td->file_ctx->compress_ipv6);
142  }
143 
144  char name[PATH_MAX];
145  snprintf(name, sizeof(name), "%s_%u-%s_%u-%s:",
146  srcip, f->sp, dstip, f->dp,
147  flags & OUTPUT_STREAMING_FLAG_TOSERVER ? "ts" : "tc");
148 
149  PrintRawUriBuf((char *)aft->buffer->buffer, &aft->buffer->offset,
150  aft->buffer->size, (uint8_t *)name,strlen(name));
151  MemBufferWriteString(aft->buffer, "\n");
152 
154  aft->buffer->size, (uint8_t *)data,data_len);
155 
156  td->file_ctx->Write((const char *)MEMBUFFER_BUFFER(aft->buffer),
157  MEMBUFFER_OFFSET(aft->buffer), td->file_ctx);
158  }
160 }
161 
162 int LogTcpDataLogger(ThreadVars *tv, void *thread_data, const Flow *f,
163  const uint8_t *data, uint32_t data_len, uint64_t tx_id, uint8_t flags)
164 {
165  SCEnter();
166  LogTcpDataLogThread *aft = thread_data;
168 
169  if (td->dir == 1)
170  LogTcpDataLoggerDir(tv, thread_data, f, data, data_len, tx_id, flags);
171  if (td->file == 1)
172  LogTcpDataLoggerFile(tv, thread_data, f, data, data_len, tx_id, flags);
173 
175 }
176 
177 TmEcode LogTcpDataLogThreadInit(ThreadVars *t, const void *initdata, void **data)
178 {
180  if (unlikely(aft == NULL))
181  return TM_ECODE_FAILED;
182 
183  if(initdata == NULL)
184  {
185  SCLogDebug("Error getting context. \"initdata\" argument NULL");
186  SCFree(aft);
187  return TM_ECODE_FAILED;
188  }
189 
191  if (aft->buffer == NULL) {
192  SCFree(aft);
193  return TM_ECODE_FAILED;
194  }
195 
196  /* Use the Output Context (file pointer and mutex) */
197  aft->tcpdatalog_ctx= ((OutputCtx *)initdata)->data;
198 
199  *data = (void *)aft;
200  return TM_ECODE_OK;
201 }
202 
204 {
206  if (aft == NULL) {
207  return TM_ECODE_OK;
208  }
209 
210  MemBufferFree(aft->buffer);
211  /* clear memory */
212  memset(aft, 0, sizeof(LogTcpDataLogThread));
213 
214  SCFree(aft);
215  return TM_ECODE_OK;
216 }
217 
218 /** \brief Create a new http log LogFileCtx.
219  * \param conf Pointer to ConfNode containing this loggers configuration.
220  * \return NULL if failure, LogFileCtx* to the file_ctx if succesful
221  * */
223 {
224  OutputInitResult result = { NULL, false };
225  char filename[PATH_MAX] = "";
226  char dirname[32] = "";
227  strlcpy(filename, DEFAULT_LOG_FILENAME, sizeof(filename));
228 
229  LogFileCtx *file_ctx = LogFileNewCtx();
230  if(file_ctx == NULL) {
231  SCLogError("couldn't create new file_ctx");
232  return result;
233  }
234 
235  LogTcpDataFileCtx *tcpdatalog_ctx = SCCalloc(1, sizeof(LogTcpDataFileCtx));
236  if (unlikely(tcpdatalog_ctx == NULL)) {
237  LogFileFreeCtx(file_ctx);
238  return result;
239  }
240 
241  tcpdatalog_ctx->file_ctx = file_ctx;
242 
243  if (conf) {
244  if (conf->name) {
245  if (strcmp(conf->name, "tcp-data") == 0) {
246  tcpdatalog_ctx->type = STREAMING_TCP_DATA;
247  snprintf(filename, sizeof(filename), "%s.log", conf->name);
248  strlcpy(dirname, "tcp", sizeof(dirname));
249  } else if (strcmp(conf->name, "http-body-data") == 0) {
250  tcpdatalog_ctx->type = STREAMING_HTTP_BODIES;
251  snprintf(filename, sizeof(filename), "%s.log", conf->name);
252  strlcpy(dirname, "http", sizeof(dirname));
253  }
254  }
255 
256  const char *logtype = SCConfNodeLookupChildValue(conf, "type");
257  if (logtype == NULL)
258  logtype = "file";
259 
260  if (strcmp(logtype, "file") == 0) {
261  tcpdatalog_ctx->file = 1;
262  } else if (strcmp(logtype, "dir") == 0) {
263  tcpdatalog_ctx->dir = 1;
264  } else if (strcmp(logtype, "both") == 0) {
265  tcpdatalog_ctx->file = 1;
266  tcpdatalog_ctx->dir = 1;
267  }
268  } else {
269  tcpdatalog_ctx->file = 1;
270  tcpdatalog_ctx->dir = 0;
271  }
272 
273  if (tcpdatalog_ctx->file == 1) {
274  SCLogInfo("opening logfile");
275  if (SCConfLogOpenGeneric(conf, file_ctx, filename, 1) < 0) {
276  LogFileFreeCtx(file_ctx);
277  SCFree(tcpdatalog_ctx);
278  return result;
279  }
280  }
281 
282  if (tcpdatalog_ctx->dir == 1) {
283  tcpdatalog_ctx->log_dir = SCConfigGetLogDirectory();
284  char dirfull[PATH_MAX];
285 
286  /* create the filename to use */
287  snprintf(dirfull, PATH_MAX, "%s/%s", tcpdatalog_ctx->log_dir, dirname);
288 
289  SCLogInfo("using directory %s", dirfull);
290 
291  if (SCMkDir(dirfull, 0700) < 0 && errno != EEXIST) {
292  SCLogError("failed to create log directory '%s': %s", dirfull, strerror(errno));
293  LogFileFreeCtx(file_ctx);
294  SCFree(tcpdatalog_ctx);
295  result = (OutputInitResult){ NULL, false };
296  return result;
297  }
298  }
299 
300  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
301  if (unlikely(output_ctx == NULL)) {
302  goto parsererror;
303  }
304 
305  output_ctx->data = tcpdatalog_ctx;
306  output_ctx->DeInit = LogTcpDataLogDeInitCtx;
307 
308  SCLogDebug("Streaming log output initialized");
309  result.ctx = output_ctx;
310  result.ok = true;
311  return result;
312 
313 parsererror:
314  LogFileFreeCtx(file_ctx);
315  SCFree(tcpdatalog_ctx);
316  SCLogError("Syntax error in custom http log format string.");
317  return result;
318 
319 }
320 
321 static void LogTcpDataLogDeInitCtx(OutputCtx *output_ctx)
322 {
323  LogTcpDataFileCtx *tcpdatalog_ctx = (LogTcpDataFileCtx *)output_ctx->data;
324  LogFileFreeCtx(tcpdatalog_ctx->file_ctx);
325  SCFree(tcpdatalog_ctx);
326  SCFree(output_ctx);
327 }
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:537
STREAMING_TCP_DATA
@ STREAMING_TCP_DATA
Definition: output-streaming.h:36
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:735
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
OutputInitResult
struct OutputInitResult_ OutputInitResult
LogTcpDataLogInitCtx
OutputInitResult LogTcpDataLogInitCtx(SCConfNode *conf)
Create a new http log LogFileCtx.
Definition: log-tcp-data.c:222
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:355
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:77
LogFileCtx_::Write
int(* Write)(const char *buffer, int buffer_len, struct LogFileCtx_ *fp)
Definition: util-logopenfile.h:92
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:878
Flow_::dp
Port dp
Definition: flow.h:371
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
LogTcpDataLogThreadInit
TmEcode LogTcpDataLogThreadInit(ThreadVars *, const void *, void **)
Definition: log-tcp-data.c:177
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:358
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:509
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:162
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
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
FLOW_IS_IPV4
#define FLOW_IS_IPV4(f)
Definition: flow.h:169
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:156
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:358
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:952
SCMkDir
#define SCMkDir(a, b)
Definition: util-path.h:45
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:34
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:499
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:203
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:360
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