]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
Add packet and payload logging to JSON alert output
authorMatt Carothers <Matt.Carothers@cox.com>
Thu, 3 Apr 2014 17:58:57 +0000 (13:58 -0400)
committerVictor Julien <victor@inliniac.net>
Mon, 28 Jul 2014 06:48:26 +0000 (08:48 +0200)
src/output-json-alert.c
src/util-print.c
src/util-print.h

index bfd646ebe3a5001ff8b4baf69a190103a9f80faa..0eb959208200df66ca74712d54636ee36c493990 100644 (file)
 #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;
 
index b02c5f009c13f2699de46443274e413e350f83a8..403545b5b7f41b45358b2223fe27520dee9bdded 100644 (file)
@@ -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
index 64a275215b37f33ab03051b2eec8df91f7a07988..bbd1e719f91b20632f67de949c5f676f26f7d803 100644 (file)
@@ -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);