From ab58ee2676b8083d791f2e9e75c940e73e51a479 Mon Sep 17 00:00:00 2001 From: Matt Carothers Date: Thu, 3 Apr 2014 13:58:57 -0400 Subject: [PATCH] Add packet and payload logging to JSON alert output --- src/output-json-alert.c | 78 +++++++++++++++++++++++++++++++++++++++++ src/util-print.c | 13 +++++++ src/util-print.h | 2 ++ 3 files changed, 93 insertions(+) diff --git a/src/output-json-alert.c b/src/output-json-alert.c index bfd646ebe3..0eb9592082 100644 --- a/src/output-json-alert.c +++ b/src/output-json-alert.c @@ -57,17 +57,32 @@ #include "util-optimize.h" #include "util-buffer.h" #include "util-logopenfile.h" +#include "util-crypt.h" #define MODULE_NAME "JsonAlertLog" #ifdef HAVE_LIBJANSSON +#define LOG_JSON_PAYLOAD 1 +#define LOG_JSON_PACKET 2 + typedef struct JsonAlertLogThread_ { /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */ LogFileCtx* file_ctx; MemBuffer *buffer; } JsonAlertLogThread; +/* Callback function to pack payload contents from a stream into a buffer + * so we can report them in JSON output. */ +static int AlertJsonPrintStreamSegmentCallback(const Packet *p, void *data, uint8_t *buf, uint32_t buflen) +{ + MemBuffer *payload = (MemBuffer *)data; + + PrintStringsToBuffer(payload->buffer, &payload->offset, payload->size, + buf, buflen); + return 1; +} + /** Handle the case where no JSON support is compiled in. * */ @@ -117,6 +132,52 @@ static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p) /* alert */ json_object_set_new(js, "alert", ajs); + /* payload */ + if (aft->file_ctx->flags & LOG_JSON_PAYLOAD) + { + /* Is this a stream? If so, pack part of it into the payload field */ + if (pa->flags & PACKET_ALERT_FLAG_STREAM_MATCH && PKT_IS_TCP(p) && p->flow != NULL && p->flow->protoctx != NULL) + { + uint8_t flag; + +#define JSON_STREAM_BUFFER_SIZE 4096 + MemBuffer *payload = MemBufferCreateNew(JSON_STREAM_BUFFER_SIZE); + MemBufferReset(payload); + + if (p->flowflags & FLOW_PKT_TOSERVER) { + flag = FLOW_PKT_TOCLIENT; + } else { + flag = FLOW_PKT_TOSERVER; + } + + StreamSegmentForEach((const Packet *)p, flag, + AlertJsonPrintStreamSegmentCallback, + (void *)payload); + json_object_set_new(js, "payload", json_string((char *)payload->buffer)); + json_object_set_new(js, "stream", json_integer(1)); + } + /* This is a single packet and not a stream */ + else + { + char payload[p->payload_len + 1]; + uint32_t offset = 0; + PrintStringsToBuffer((uint8_t *)payload, &offset, p->payload_len + 1, + p->payload, p->payload_len); + json_object_set_new(js, "payload", json_string(payload)); + json_object_set_new(js, "stream", json_integer(0)); + } + } + + /* base64-encoded full packet */ + if (aft->file_ctx->flags & LOG_JSON_PACKET) + { + unsigned long len = GET_PKT_LEN(p) * 2; + unsigned char encoded_packet[len]; + Base64Encode((unsigned char*) GET_PKT_DATA(p), GET_PKT_LEN(p), encoded_packet, &len); + json_object_set_new(js, "packet", json_string((char *)encoded_packet)); + } + + OutputJSONBuffer(js, aft->file_ctx, aft->buffer); json_object_del(js, "alert"); } @@ -271,6 +332,7 @@ static void JsonAlertLogDeInitCtxSub(OutputCtx *output_ctx) } #define DEFAULT_LOG_FILENAME "alert.json" + /** * \brief Create a new LogFileCtx for "fast" output style. * \param conf The configuration node for this output. @@ -311,6 +373,22 @@ static OutputCtx *JsonAlertLogInitCtxSub(ConfNode *conf, OutputCtx *parent_ctx) if (unlikely(output_ctx == NULL)) return NULL; + if (conf) { + const char *payload = ConfNodeLookupChildValue(conf, "payload"); + const char *packet = ConfNodeLookupChildValue(conf, "packet"); + + if (payload != NULL) { + if (ConfValIsTrue(payload)) { + ajt->file_ctx->flags |= LOG_JSON_PAYLOAD; + } + } + if (packet != NULL) { + if (ConfValIsTrue(packet)) { + ajt->file_ctx->flags |= LOG_JSON_PACKET; + } + } + } + output_ctx->data = ajt->file_ctx; output_ctx->DeInit = JsonAlertLogDeInitCtxSub; diff --git a/src/util-print.c b/src/util-print.c index b02c5f009c..403545b5b7 100644 --- a/src/util-print.c +++ b/src/util-print.c @@ -215,6 +215,19 @@ void PrintRawDataToBuffer(uint8_t *dst_buf, uint32_t *dst_buf_offset_ptr, uint32 return; } +void PrintStringsToBuffer(uint8_t *dst_buf, uint32_t *dst_buf_offset_ptr, uint32_t dst_buf_size, + uint8_t *src_buf, uint32_t src_buf_len) +{ + uint32_t ch = 0; + for (ch = 0; ch < src_buf_len; ch++) { + PrintBufferData((char *)dst_buf, dst_buf_offset_ptr, dst_buf_size, + "%c", + isprint((uint8_t)src_buf[ch]) || src_buf[ch] == '\n' || src_buf[ch] == '\r' ? (uint8_t)src_buf[ch] : '.'); + } + + return; +} + #ifndef s6_addr16 # define s6_addr16 __u6_addr.__u6_addr16 #endif diff --git a/src/util-print.h b/src/util-print.h index 64a275215b..bbd1e719f9 100644 --- a/src/util-print.h +++ b/src/util-print.h @@ -49,6 +49,8 @@ void PrintRawJsonFp(FILE *, uint8_t *, uint32_t); void PrintRawDataFp(FILE *, uint8_t *, uint32_t); void PrintRawDataToBuffer(uint8_t *dst_buf, uint32_t *dst_buf_offset_ptr, uint32_t dst_buf_size, uint8_t *src_buf, uint32_t src_buf_len); +void PrintStringsToBuffer(uint8_t *dst_buf, uint32_t *dst_buf_offset_ptr, uint32_t dst_buf_size, + uint8_t *src_buf, uint32_t src_buf_len); void PrintRawLineHexBuf(char *, uint32_t, uint8_t *, uint32_t ); const char *PrintInet(int , const void *, char *, socklen_t);