suricata
output-json-http.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 * Implements HTTP JSON logging portion of the engine.
24 */
25
26#include "suricata-common.h"
27#include "detect.h"
28#include "pkt-var.h"
29#include "conf.h"
30
31#include "threads.h"
32#include "threadvars.h"
33#include "tm-threads.h"
34
35#include "util-print.h"
36#include "util-unittest.h"
37
38#include "util-debug.h"
39
40#include "output.h"
41#include "app-layer-htp.h"
42#include "app-layer-htp-file.h"
43#include "app-layer-htp-xff.h"
44#include "app-layer.h"
45#include "app-layer-parser.h"
46#include "util-privs.h"
47#include "util-buffer.h"
48#include "util-proto-name.h"
49#include "util-logopenfile.h"
50#include "util-time.h"
51#include "output-json.h"
52#include "output-json-alert.h"
53#include "output-json-http.h"
54#include "util-byte.h"
55
56typedef struct LogHttpFileCtx_ {
57 uint32_t flags; /** Store mode */
58 uint64_t fields;/** Store fields */
63
69
70#define MAX_SIZE_HEADER_NAME 256
71#define MAX_SIZE_HEADER_VALUE 2048
72
73#define LOG_HTTP_DEFAULT 0
74#define LOG_HTTP_EXTENDED 1
75#define LOG_HTTP_REQUEST 2 /* request field */
76#define LOG_HTTP_ARRAY 4 /* require array handling */
77#define LOG_HTTP_REQ_HEADERS 8
78#define LOG_HTTP_RES_HEADERS 16
79
136
137struct {
138 const char *config_field;
139 const char *htp_field;
140 uint32_t flags;
141} http_fields[] = {
142 { "accept", "accept", LOG_HTTP_REQUEST },
143 { "accept_charset", "accept-charset", LOG_HTTP_REQUEST },
144 { "accept_encoding", "accept-encoding", LOG_HTTP_REQUEST },
145 { "accept_language", "accept-language", LOG_HTTP_REQUEST },
146 { "accept_datetime", "accept-datetime", LOG_HTTP_REQUEST },
147 { "authorization", "authorization", LOG_HTTP_REQUEST },
148 { "cache_control", "cache-control", LOG_HTTP_REQUEST },
149 { "cookie", "cookie", LOG_HTTP_REQUEST | LOG_HTTP_ARRAY },
150 { "from", "from", LOG_HTTP_REQUEST },
151 { "max_forwards", "max-forwards", LOG_HTTP_REQUEST },
152 { "origin", "origin", LOG_HTTP_REQUEST },
153 { "pragma", "pragma", LOG_HTTP_REQUEST },
154 { "proxy_authorization", "proxy-authorization", LOG_HTTP_REQUEST },
155 { "range", "range", LOG_HTTP_REQUEST },
156 { "te", "te", LOG_HTTP_REQUEST },
157 { "via", "via", LOG_HTTP_REQUEST },
158 { "x_requested_with", "x-requested-with", LOG_HTTP_REQUEST },
159 { "dnt", "dnt", LOG_HTTP_REQUEST },
160 { "x_forwarded_proto", "x-forwarded-proto", LOG_HTTP_REQUEST },
161 { "x_authenticated_user", "x-authenticated-user", LOG_HTTP_REQUEST },
162 { "x_flash_version", "x-flash-version", LOG_HTTP_REQUEST },
163 { "accept_range", "accept-range", 0 },
164 { "age", "age", 0 },
165 { "allow", "allow", 0 },
166 { "connection", "connection", 0 },
167 { "content_encoding", "content-encoding", 0 },
168 { "content_language", "content-language", 0 },
169 { "content_length", "content-length", 0 },
170 { "content_location", "content-location", 0 },
171 { "content_md5", "content-md5", 0 },
172 { "content_range", "content-range", 0 },
173 { "content_type", "content-type", 0 },
174 { "date", "date", 0 },
175 { "etag", "etags", 0 },
176 { "expires", "expires", 0 },
177 { "last_modified", "last-modified", 0 },
178 { "link", "link", 0 },
179 { "location", "location", 0 },
180 { "proxy_authenticate", "proxy-authenticate", 0 },
181 { "referer", "referer", LOG_HTTP_EXTENDED },
182 { "refresh", "refresh", 0 },
183 { "retry_after", "retry-after", 0 },
184 { "server", "server", 0 },
185 { "set_cookie", "set-cookie", 0 },
186 { "trailer", "trailer", 0 },
187 { "transfer_encoding", "transfer-encoding", 0 },
188 { "upgrade", "upgrade", 0 },
189 { "vary", "vary", 0 },
190 { "warning", "warning", 0 },
191 { "www_authenticate", "www-authenticate", 0 },
192 { "true_client_ip", "true-client-ip", LOG_HTTP_REQUEST },
193 { "org_src_ip", "org-src-ip", LOG_HTTP_REQUEST },
194 { "x_bluecoat_via", "x-bluecoat-via", LOG_HTTP_REQUEST },
196
197static void EveHttpLogJSONBasic(SCJsonBuilder *js, htp_tx_t *tx)
198{
199 /* hostname */
200 if (htp_tx_request_hostname(tx) != NULL) {
201 SCJbSetStringFromBytes(js, "hostname", bstr_ptr(htp_tx_request_hostname(tx)),
202 (uint32_t)bstr_len(htp_tx_request_hostname(tx)));
203 }
204
205 /* port */
206 /* NOTE: this field will be set ONLY if the port is present in the
207 * hostname. It may be present in the header "Host" or in the URL.
208 * There is no connection (from the suricata point of view) between this
209 * port and the TCP destination port of the flow.
210 */
211 if (htp_tx_request_port_number(tx) >= 0) {
212 SCJbSetUint(js, "http_port", htp_tx_request_port_number(tx));
213 }
214
215 /* uri */
216 if (htp_tx_request_uri(tx) != NULL) {
217 SCJbSetStringFromBytes(js, "url", bstr_ptr(htp_tx_request_uri(tx)),
218 (uint32_t)bstr_len(htp_tx_request_uri(tx)));
219 }
220
221 if (htp_tx_request_headers(tx) != NULL) {
222 /* user agent */
223 const htp_header_t *h_user_agent = htp_tx_request_header(tx, "user-agent");
224 if (h_user_agent != NULL) {
225 SCJbSetStringFromBytes(js, "http_user_agent", htp_header_value_ptr(h_user_agent),
226 (uint32_t)htp_header_value_len(h_user_agent));
227 }
228
229 /* x-forwarded-for */
230 const htp_header_t *h_x_forwarded_for = htp_tx_request_header(tx, "x-forwarded-for");
231 if (h_x_forwarded_for != NULL) {
232 SCJbSetStringFromBytes(js, "xff", htp_header_value_ptr(h_x_forwarded_for),
233 (uint32_t)htp_header_value_len(h_x_forwarded_for));
234 }
235 }
236
237 /* content-type */
238 if (htp_tx_response_headers(tx) != NULL) {
239 const htp_header_t *h_content_type = htp_tx_response_header(tx, "content-type");
240 if (h_content_type != NULL) {
241 const size_t size = htp_header_value_len(h_content_type) * 2 + 1;
242 char string[size];
243 BytesToStringBuffer(htp_header_value_ptr(h_content_type),
244 htp_header_value_len(h_content_type), string, size);
245 char *p = strchr(string, ';');
246 if (p != NULL)
247 *p = '\0';
248 SCJbSetString(js, "http_content_type", string);
249 }
250 const htp_header_t *h_content_range = htp_tx_response_header(tx, "content-range");
251 if (h_content_range != NULL) {
252 SCJbOpenObject(js, "content_range");
253 SCJbSetStringFromBytes(js, "raw", htp_header_value_ptr(h_content_range),
254 (uint32_t)htp_header_value_len(h_content_range));
255 HTTPContentRange crparsed;
256 if (HTPParseContentRange(htp_header_value(h_content_range), &crparsed) == 0) {
257 if (crparsed.start >= 0)
258 SCJbSetUint(js, "start", crparsed.start);
259 if (crparsed.end >= 0)
260 SCJbSetUint(js, "end", crparsed.end);
261 if (crparsed.size >= 0)
262 SCJbSetUint(js, "size", crparsed.size);
263 }
264 SCJbClose(js);
265 }
266 }
267}
268
269static void EveHttpLogJSONExtended(SCJsonBuilder *js, htp_tx_t *tx)
270{
271 /* referer */
272 const htp_header_t *h_referer = NULL;
273 if (htp_tx_request_headers(tx) != NULL) {
274 h_referer = htp_tx_request_header(tx, "referer");
275 }
276 if (h_referer != NULL) {
277 SCJbSetStringFromBytes(js, "http_refer", htp_header_value_ptr(h_referer),
278 (uint32_t)htp_header_value_len(h_referer));
279 }
280
281 /* method */
282 if (htp_tx_request_method(tx) != NULL) {
283 SCJbSetStringFromBytes(js, "http_method", bstr_ptr(htp_tx_request_method(tx)),
284 (uint32_t)bstr_len(htp_tx_request_method(tx)));
285 }
286
287 /* protocol */
288 if (htp_tx_request_protocol(tx) != NULL) {
289 SCJbSetStringFromBytes(js, "protocol", bstr_ptr(htp_tx_request_protocol(tx)),
290 (uint32_t)bstr_len(htp_tx_request_protocol(tx)));
291 }
292
293 /* response status */
294 const int resp = htp_tx_response_status_number(tx);
295 if (resp > 0) {
296 SCJbSetUint(js, "status", (uint32_t)resp);
297 } else if (htp_tx_response_status(tx) != NULL) {
298 SCJbSetStringFromBytes(js, "status_string", bstr_ptr(htp_tx_response_status(tx)),
299 (uint32_t)bstr_len(htp_tx_response_status(tx)));
300 }
301
302 const htp_header_t *h_location = htp_tx_response_header(tx, "location");
303 if (h_location != NULL) {
304 SCJbSetStringFromBytes(js, "redirect", htp_header_value_ptr(h_location),
305 (uint32_t)htp_header_value_len(h_location));
306 }
307
308 /* length */
309 SCJbSetUint(js, "length", htp_tx_response_message_len(tx));
310}
311
312static void EveHttpLogJSONHeaders(
313 SCJsonBuilder *js, uint32_t direction, htp_tx_t *tx, LogHttpFileCtx *http_ctx)
314{
315 const htp_headers_t *headers = direction & LOG_HTTP_REQ_HEADERS ? htp_tx_request_headers(tx)
316 : htp_tx_response_headers(tx);
317 char name[MAX_SIZE_HEADER_NAME] = {0};
318 char value[MAX_SIZE_HEADER_VALUE] = {0};
319 size_t n = htp_headers_size(headers);
320 SCJsonBuilderMark mark = { 0, 0, 0 };
321 SCJbGetMark(js, &mark);
322 bool array_empty = true;
323 SCJbOpenArray(js, direction & LOG_HTTP_REQ_HEADERS ? "request_headers" : "response_headers");
324 for (size_t i = 0; i < n; i++) {
325 const htp_header_t *h = htp_headers_get_index(headers, i);
326 if ((http_ctx->flags & direction) == 0 && http_ctx->fields != 0) {
327 bool tolog = false;
328 for (HttpField f = HTTP_FIELD_ACCEPT; f < HTTP_FIELD_SIZE; f++) {
329 if ((http_ctx->fields & (1ULL << f)) != 0) {
330 /* prevent logging a field twice if extended logging is
331 enabled */
332 if (((http_ctx->flags & LOG_HTTP_EXTENDED) == 0) ||
333 ((http_ctx->flags & LOG_HTTP_EXTENDED) !=
334 (http_fields[f].flags & LOG_HTTP_EXTENDED))) {
335 if (bstr_cmp_c_nocase(htp_header_name(h), http_fields[f].htp_field)) {
336 tolog = true;
337 break;
338 }
339 }
340 }
341 }
342 if (!tolog) {
343 continue;
344 }
345 }
346 array_empty = false;
347 SCJbStartObject(js);
348 size_t size_name = htp_header_name_len(h) < MAX_SIZE_HEADER_NAME - 1
349 ? htp_header_name_len(h)
351 memcpy(name, htp_header_name_ptr(h), size_name);
352 name[size_name] = '\0';
353 SCJbSetString(js, "name", name);
354 size_t size_value = htp_header_value_len(h) < MAX_SIZE_HEADER_VALUE - 1
355 ? htp_header_value_len(h)
357 memcpy(value, htp_header_value_ptr(h), size_value);
358 value[size_value] = '\0';
359 SCJbSetString(js, "value", value);
360 SCJbClose(js);
361 }
362 if (array_empty) {
363 SCJbRestoreMark(js, &mark);
364 } else {
365 // Close array.
366 SCJbClose(js);
367 }
368}
369
370static void BodyPrintableBuffer(SCJsonBuilder *js, HtpBody *body, const char *key)
371{
372 if (body->sb != NULL && body->sb->region.buf != NULL) {
373 uint32_t offset = 0;
374 const uint8_t *body_data;
375 uint32_t body_data_len;
376 uint64_t body_offset;
377
378 if (StreamingBufferGetData(body->sb, &body_data,
379 &body_data_len, &body_offset) == 0) {
380 return;
381 }
382
383 uint8_t printable_buf[body_data_len + 1];
384 PrintStringsToBuffer(printable_buf, &offset, body_data_len + 1, body_data, body_data_len);
385 if (offset > 0) {
386 SCJbSetString(js, key, (char *)printable_buf);
387 }
388 }
389}
390
391void EveHttpLogJSONBodyPrintable(SCJsonBuilder *js, Flow *f, uint64_t tx_id)
392{
393 HtpState *htp_state = (HtpState *)FlowGetAppState(f);
394 if (htp_state) {
395 htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, tx_id);
396 if (tx) {
397 HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx);
398 BodyPrintableBuffer(js, &htud->request_body, "http_request_body_printable");
399 BodyPrintableBuffer(js, &htud->response_body, "http_response_body_printable");
400 }
401 }
402}
403
404static void BodyBase64Buffer(SCJsonBuilder *js, HtpBody *body, const char *key)
405{
406 if (body->sb != NULL && body->sb->region.buf != NULL) {
407 const uint8_t *body_data;
408 uint32_t body_data_len;
409 uint64_t body_offset;
410
411 if (StreamingBufferGetData(body->sb, &body_data,
412 &body_data_len, &body_offset) == 0) {
413 return;
414 }
415
416 SCJbSetBase64(js, key, body_data, body_data_len);
417 }
418}
419
420void EveHttpLogJSONBodyBase64(SCJsonBuilder *js, Flow *f, uint64_t tx_id)
421{
422 HtpState *htp_state = (HtpState *)FlowGetAppState(f);
423 if (htp_state) {
424 htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, tx_id);
425 if (tx) {
426 HtpTxUserData *htud = (HtpTxUserData *)htp_tx_get_user_data(tx);
427 BodyBase64Buffer(js, &htud->request_body, "http_request_body");
428 BodyBase64Buffer(js, &htud->response_body, "http_response_body");
429 }
430 }
431}
432
433/* JSON format logging */
434static void EveHttpLogJSON(JsonHttpLogThread *aft, SCJsonBuilder *js, htp_tx_t *tx, uint64_t tx_id)
435{
436 LogHttpFileCtx *http_ctx = aft->httplog_ctx;
437 SCJbOpenObject(js, "http");
438
439 EveHttpLogJSONBasic(js, tx);
440 if (http_ctx->flags & LOG_HTTP_EXTENDED)
441 EveHttpLogJSONExtended(js, tx);
442 if (http_ctx->flags & LOG_HTTP_REQ_HEADERS || http_ctx->fields != 0)
443 EveHttpLogJSONHeaders(js, LOG_HTTP_REQ_HEADERS, tx, http_ctx);
444 if (http_ctx->flags & LOG_HTTP_RES_HEADERS || http_ctx->fields != 0)
445 EveHttpLogJSONHeaders(js, LOG_HTTP_RES_HEADERS, tx, http_ctx);
446
447 SCJbClose(js);
448}
449
450static int JsonHttpLogger(ThreadVars *tv, void *thread_data, const Packet *p, Flow *f, void *alstate, void *txptr, uint64_t tx_id)
451{
452 SCEnter();
453
454 htp_tx_t *tx = txptr;
455 JsonHttpLogThread *jhl = (JsonHttpLogThread *)thread_data;
456
457 SCJsonBuilder *js = CreateEveHeaderWithTxId(
458 p, LOG_DIR_FLOW, "http", NULL, tx_id, jhl->httplog_ctx->eve_ctx);
459 if (unlikely(js == NULL))
460 return TM_ECODE_OK;
461
462 SCLogDebug("got a HTTP request and now logging !!");
463
464 EveHttpLogJSON(jhl, js, tx, tx_id);
465 HttpXFFCfg *xff_cfg = jhl->httplog_ctx->xff_cfg != NULL ?
467
468 /* xff header */
469 if ((xff_cfg != NULL) && !(xff_cfg->flags & XFF_DISABLED) && p->flow != NULL) {
470 int have_xff_ip = 0;
471 char buffer[XFF_MAXLEN];
472
473 have_xff_ip = HttpXFFGetIPFromTx(p->flow, tx_id, xff_cfg, buffer, XFF_MAXLEN);
474
475 if (have_xff_ip) {
476 if (xff_cfg->flags & XFF_EXTRADATA) {
477 SCJbSetString(js, "xff", buffer);
478 }
479 else if (xff_cfg->flags & XFF_OVERWRITE) {
480 if (p->flowflags & FLOW_PKT_TOCLIENT) {
481 SCJbSetString(js, "dest_ip", buffer);
482 } else {
483 SCJbSetString(js, "src_ip", buffer);
484 }
485 }
486 }
487 }
488
489 OutputJsonBuilderBuffer(tv, p, p->flow, js, jhl->ctx);
490 SCJbFree(js);
491
493}
494
495bool EveHttpAddMetadata(const Flow *f, uint64_t tx_id, SCJsonBuilder *js)
496{
497 HtpState *htp_state = (HtpState *)FlowGetAppState(f);
498 if (htp_state) {
499 htp_tx_t *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP1, htp_state, tx_id);
500
501 if (tx) {
502 EveHttpLogJSONBasic(js, tx);
503 EveHttpLogJSONExtended(js, tx);
504 return true;
505 }
506 }
507
508 return false;
509}
510
511static void OutputHttpLogDeinitSub(OutputCtx *output_ctx)
512{
513 LogHttpFileCtx *http_ctx = output_ctx->data;
514 if (http_ctx->xff_cfg) {
515 SCFree(http_ctx->xff_cfg);
516 }
517 SCFree(http_ctx);
518 SCFree(output_ctx);
519}
520
521static OutputInitResult OutputHttpLogInitSub(SCConfNode *conf, OutputCtx *parent_ctx)
522{
523 OutputInitResult result = { NULL, false };
524 OutputJsonCtx *ojc = parent_ctx->data;
525
526 LogHttpFileCtx *http_ctx = SCCalloc(1, sizeof(LogHttpFileCtx));
527 if (unlikely(http_ctx == NULL))
528 return result;
529 memset(http_ctx, 0x00, sizeof(*http_ctx));
530
531 OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
532 if (unlikely(output_ctx == NULL)) {
533 SCFree(http_ctx);
534 return result;
535 }
536
537 http_ctx->flags = LOG_HTTP_DEFAULT;
538 http_ctx->eve_ctx = ojc;
539
540 if (conf) {
541 const char *extended = SCConfNodeLookupChildValue(conf, "extended");
542
543 if (extended != NULL) {
544 if (SCConfValIsTrue(extended)) {
545 http_ctx->flags = LOG_HTTP_EXTENDED;
546 }
547 }
548
549 const char *all_headers = SCConfNodeLookupChildValue(conf, "dump-all-headers");
550 if (all_headers != NULL) {
551 if (strncmp(all_headers, "both", 4) == 0) {
552 http_ctx->flags |= LOG_HTTP_REQ_HEADERS;
553 http_ctx->flags |= LOG_HTTP_RES_HEADERS;
554 } else if (strncmp(all_headers, "request", 7) == 0) {
555 http_ctx->flags |= LOG_HTTP_REQ_HEADERS;
556 } else if (strncmp(all_headers, "response", 8) == 0) {
557 http_ctx->flags |= LOG_HTTP_RES_HEADERS;
558 }
559 }
560 SCConfNode *custom;
561 if ((custom = SCConfNodeLookupChild(conf, "custom")) != NULL) {
562 if ((http_ctx->flags & (LOG_HTTP_REQ_HEADERS | LOG_HTTP_RES_HEADERS)) ==
564 SCLogWarning("No need for custom as dump-all-headers is already present");
565 }
566 SCConfNode *field;
567 TAILQ_FOREACH (field, &custom->head, next) {
568 HttpField f;
569 for (f = HTTP_FIELD_ACCEPT; f < HTTP_FIELD_SIZE; f++) {
570 if ((strcmp(http_fields[f].config_field, field->val) == 0) ||
571 (strcasecmp(http_fields[f].htp_field, field->val) == 0)) {
572 http_ctx->fields |= (1ULL << f);
573 break;
574 }
575 }
576 }
577 }
578 }
579
580 if (conf != NULL && SCConfNodeLookupChild(conf, "xff") != NULL) {
581 http_ctx->xff_cfg = SCCalloc(1, sizeof(HttpXFFCfg));
582 if (http_ctx->xff_cfg != NULL) {
583 HttpXFFGetCfg(conf, http_ctx->xff_cfg);
584 }
585 } else if (ojc->xff_cfg) {
586 http_ctx->parent_xff_cfg = ojc->xff_cfg;
587 }
588
589 output_ctx->data = http_ctx;
590 output_ctx->DeInit = OutputHttpLogDeinitSub;
591
592 /* enable the logger for the app layer */
594
595 result.ctx = output_ctx;
596 result.ok = true;
597 return result;
598}
599
600static TmEcode JsonHttpLogThreadInit(ThreadVars *t, const void *initdata, void **data)
601{
603 if (unlikely(aft == NULL))
604 return TM_ECODE_FAILED;
605
606 if(initdata == NULL)
607 {
608 SCLogDebug("Error getting context for EveLogHTTP. \"initdata\" argument NULL");
609 goto error_exit;
610 }
611
612 /* Use the Output Context (file pointer and mutex) */
613 aft->httplog_ctx = ((OutputCtx *)initdata)->data; //TODO
614
615 aft->ctx = CreateEveThreadCtx(t, aft->httplog_ctx->eve_ctx);
616 if (!aft->ctx) {
617 goto error_exit;
618 }
619
620 *data = (void *)aft;
621 return TM_ECODE_OK;
622
623error_exit:
624 SCFree(aft);
625 return TM_ECODE_FAILED;
626}
627
628static TmEcode JsonHttpLogThreadDeinit(ThreadVars *t, void *data)
629{
631 if (aft == NULL) {
632 return TM_ECODE_OK;
633 }
634
635 FreeEveThreadCtx(aft->ctx);
636
637 /* clear memory */
638 memset(aft, 0, sizeof(JsonHttpLogThread));
639
640 SCFree(aft);
641 return TM_ECODE_OK;
642}
643
645{
646 /* register as child of eve-log */
647 OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", "JsonHttpLog", "eve-log.http",
648 OutputHttpLogInitSub, ALPROTO_HTTP1, JsonHttpLogger, JsonHttpLogThreadInit,
649 JsonHttpLogThreadDeinit);
650}
int HTPParseContentRange(const bstr *rawvalue, HTTPContentRange *range)
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.
void HttpXFFGetCfg(SCConfNode *conf, HttpXFFCfg *result)
Function to return XFF configuration from a configuration node.
#define XFF_MAXLEN
#define XFF_EXTRADATA
#define XFF_OVERWRITE
#define XFF_DISABLED
struct HtpBodyChunk_ * next
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
void SCAppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
@ ALPROTO_HTTP1
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition conf.c:796
int SCConfValIsTrue(const char *val)
Check if a value is true.
Definition conf.c:551
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition conf.c:824
#define FLOW_PKT_TOCLIENT
Definition flow.h:234
ThreadVars * tv
@ LOG_DIR_FLOW
OutputJsonThreadCtx * CreateEveThreadCtx(ThreadVars *t, OutputJsonCtx *ctx)
void FreeEveThreadCtx(OutputJsonThreadCtx *ctx)
const char * config_field
struct LogHttpFileCtx_ LogHttpFileCtx
void EveHttpLogJSONBodyPrintable(SCJsonBuilder *js, Flow *f, uint64_t tx_id)
#define LOG_HTTP_ARRAY
const char * htp_field
#define LOG_HTTP_EXTENDED
#define LOG_HTTP_REQ_HEADERS
#define LOG_HTTP_DEFAULT
struct @144 http_fields[]
uint32_t flags
bool EveHttpAddMetadata(const Flow *f, uint64_t tx_id, SCJsonBuilder *js)
void EveHttpLogJSONBodyBase64(SCJsonBuilder *js, Flow *f, uint64_t tx_id)
#define LOG_HTTP_REQUEST
void JsonHttpLogRegister(void)
HttpField
@ HTTP_FIELD_CONTENT_ENCODING
@ HTTP_FIELD_REFRESH
@ HTTP_FIELD_CONTENT_TYPE
@ HTTP_FIELD_X_BLUECOAT_VIA
@ HTTP_FIELD_TE
@ HTTP_FIELD_X_REQUESTED_WITH
@ HTTP_FIELD_CONTENT_LOCATION
@ HTTP_FIELD_ALLOW
@ HTTP_FIELD_CACHE_CONTROL
@ HTTP_FIELD_VIA
@ HTTP_FIELD_X_AUTHENTICATED_USER
@ HTTP_FIELD_LAST_MODIFIED
@ HTTP_FIELD_RANGE
@ HTTP_FIELD_RETRY_AFTER
@ HTTP_FIELD_PROXY_AUTHORIZATION
@ HTTP_FIELD_LINK
@ HTTP_FIELD_ACCEPT_RANGES
@ HTTP_FIELD_ORIGIN
@ HTTP_FIELD_CONTENT_MD5
@ HTTP_FIELD_X_FLASH_VERSION
@ HTTP_FIELD_X_FORWARDED_PROTO
@ HTTP_FIELD_CONTENT_LENGTH
@ HTTP_FIELD_REFERRER
@ HTTP_FIELD_ORG_SRC_IP
@ HTTP_FIELD_CONTENT_LANGUAGE
@ HTTP_FIELD_FROM
@ HTTP_FIELD_AUTHORIZATION
@ HTTP_FIELD_SERVER
@ HTTP_FIELD_COOKIE
@ HTTP_FIELD_PROXY_AUTHENTICATE
@ HTTP_FIELD_DATE
@ HTTP_FIELD_ETAG
@ HTTP_FIELD_CONTENT_RANGE
@ HTTP_FIELD_UPGRADE
@ HTTP_FIELD_TRAILER
@ HTTP_FIELD_PRAGMA
@ HTTP_FIELD_TRUE_CLIENT_IP
@ HTTP_FIELD_SIZE
@ HTTP_FIELD_AGE
@ HTTP_FIELD_MAX_FORWARDS
@ HTTP_FIELD_WWW_AUTHENTICATE
@ HTTP_FIELD_ACCEPT_LANGUAGE
@ HTTP_FIELD_TRANSFER_ENCODING
@ HTTP_FIELD_WARNING
@ HTTP_FIELD_LOCATION
@ HTTP_FIELD_ACCEPT_ENCODING
@ HTTP_FIELD_ACCEPT
@ HTTP_FIELD_EXPIRES
@ HTTP_FIELD_CONNECTION
@ HTTP_FIELD_ACCEPT_CHARSET
@ HTTP_FIELD_SET_COOKIE
@ HTTP_FIELD_DNT
@ HTTP_FIELD_VARY
@ HTTP_FIELD_ACCEPT_DATETIME
#define MAX_SIZE_HEADER_NAME
#define MAX_SIZE_HEADER_VALUE
struct JsonHttpLogThread_ JsonHttpLogThread
#define LOG_HTTP_RES_HEADERS
void OutputJsonBuilderBuffer(ThreadVars *tv, const Packet *p, Flow *f, SCJsonBuilder *js, OutputJsonThreadCtx *ctx)
SCJsonBuilder * CreateEveHeaderWithTxId(const Packet *p, enum SCOutputJsonLogDirection dir, const char *event_type, JsonAddrInfo *addr, uint64_t tx_id, OutputJsonCtx *eve_ctx)
void OutputRegisterTxSubModule(LoggerId id, const char *parent_name, const char *name, const char *conf_name, OutputInitSubFunc InitFunc, AppProto alproto, TxLogger TxLogFunc, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit)
Definition output.c:406
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:252
Flow data structure.
Definition flow.h:356
StreamingBuffer * sb
HtpBody response_body
OutputJsonThreadCtx * ctx
LogHttpFileCtx * httplog_ctx
OutputJsonCtx * eve_ctx
HttpXFFCfg * xff_cfg
HttpXFFCfg * parent_xff_cfg
void * data
Definition tm-modules.h:91
void(* DeInit)(struct OutputCtx_ *)
Definition tm-modules.h:94
OutputCtx * ctx
Definition output.h:47
HttpXFFCfg * xff_cfg
Definition output-json.h:79
uint8_t flowflags
Definition decode.h:532
struct Flow_ * flow
Definition decode.h:546
char * val
Definition conf.h:39
StreamingBufferRegion region
Per thread variable structure.
Definition threadvars.h:58
@ LOGGER_JSON_TX
@ TM_ECODE_FAILED
@ TM_ECODE_OK
const char * name
void BytesToStringBuffer(const uint8_t *bytes, size_t nbytes, char *outstr, size_t outlen)
Turn byte array into string.
Definition util-byte.c:85
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define unlikely(expr)
void PrintStringsToBuffer(uint8_t *dst_buf, uint32_t *dst_buf_offset_ptr, uint32_t dst_buf_size, const uint8_t *src_buf, const uint32_t src_buf_len)
Definition util-print.c:195
int StreamingBufferGetData(const StreamingBuffer *sb, const uint8_t **data, uint32_t *data_len, uint64_t *stream_offset)
uint64_t offset