static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p) { MemBuffer *payload = aft->payload_buffer; AlertJsonOutputCtx *json_output_ctx = aft->json_output_ctx; json_t *hjs = NULL; int i; if (p->alerts.cnt == 0 && !(p->flags & PKT_HAS_TAG)) return TM_ECODE_OK; json_t *js = CreateJSONHeader((Packet *)p, 0, "alert"); if (unlikely(js == NULL)) return TM_ECODE_OK; for (i = 0; i < p->alerts.cnt; i++) { const PacketAlert *pa = &p->alerts.alerts[i]; if (unlikely(pa->s == NULL)) { continue; } MemBufferReset(aft->json_buffer); /* alert */ AlertJsonHeader(p, pa, js); if (json_output_ctx->flags & LOG_JSON_HTTP) { if (p->flow != NULL) { uint16_t proto = FlowGetAppProtocol(p->flow); /* http alert */ if (proto == ALPROTO_HTTP) { hjs = JsonHttpAddMetadata(p->flow, pa->tx_id); if (hjs) json_object_set_new(js, "http", hjs); } } } if (json_output_ctx->flags & LOG_JSON_TLS) { if (p->flow != NULL) { uint16_t proto = FlowGetAppProtocol(p->flow); /* http alert */ if (proto == ALPROTO_TLS) AlertJsonTls(p->flow, js); } } if (json_output_ctx->flags & LOG_JSON_SSH) { if (p->flow != NULL) { uint16_t proto = FlowGetAppProtocol(p->flow); /* http alert */ if (proto == ALPROTO_SSH) AlertJsonSsh(p->flow, js); } } if (json_output_ctx->flags & LOG_JSON_SMTP) { if (p->flow != NULL) { uint16_t proto = FlowGetAppProtocol(p->flow); /* http alert */ if (proto == ALPROTO_SMTP) { hjs = JsonSMTPAddMetadata(p->flow, pa->tx_id); if (hjs) json_object_set_new(js, "smtp", hjs); hjs = JsonEmailAddMetadata(p->flow, pa->tx_id); if (hjs) json_object_set_new(js, "email", hjs); } } } /* payload */ if (json_output_ctx->flags & (LOG_JSON_PAYLOAD | LOG_JSON_PAYLOAD_BASE64)) { int stream = (p->proto == IPPROTO_TCP) ? (pa->flags & (PACKET_ALERT_FLAG_STATE_MATCH | PACKET_ALERT_FLAG_STREAM_MATCH) ? 1 : 0) : 0; /* Is this a stream? If so, pack part of it into the payload field */ if (stream) { uint8_t flag; MemBufferReset(payload); if (p->flowflags & FLOW_PKT_TOSERVER) { flag = FLOW_PKT_TOCLIENT; } else { flag = FLOW_PKT_TOSERVER; } StreamSegmentForEach((const Packet *)p, flag, AlertJsonDumpStreamSegmentCallback, (void *)payload); if (json_output_ctx->flags & LOG_JSON_PAYLOAD_BASE64) { unsigned long len = json_output_ctx->payload_buffer_size * 2; uint8_t encoded[len]; Base64Encode(payload->buffer, payload->offset, encoded, &len); json_object_set_new(js, "payload", json_string((char *)encoded)); } if (json_output_ctx->flags & LOG_JSON_PAYLOAD) { uint8_t printable_buf[payload->offset + 1]; uint32_t offset = 0; PrintStringsToBuffer(printable_buf, &offset, sizeof(printable_buf), payload->buffer, payload->offset); json_object_set_new(js, "payload_printable", json_string((char *)printable_buf)); } } else { /* This is a single packet and not a stream */ if (json_output_ctx->flags & LOG_JSON_PAYLOAD_BASE64) { unsigned long len = p->payload_len * 2 + 1; uint8_t encoded[len]; Base64Encode(p->payload, p->payload_len, encoded, &len); json_object_set_new(js, "payload", json_string((char *)encoded)); } if (json_output_ctx->flags & LOG_JSON_PAYLOAD) { uint8_t printable_buf[p->payload_len + 1]; uint32_t offset = 0; PrintStringsToBuffer(printable_buf, &offset, p->payload_len + 1, p->payload, p->payload_len); json_object_set_new(js, "payload_printable", json_string((char *)printable_buf)); } } json_object_set_new(js, "stream", json_integer(stream)); } /* base64-encoded full packet */ if (json_output_ctx->flags & LOG_JSON_PACKET) { AlertJsonPacket(p, js); } HttpXFFCfg *xff_cfg = json_output_ctx->xff_cfg; /* xff header */ if ((xff_cfg != NULL) && !(xff_cfg->flags & XFF_DISABLED) && p->flow != NULL) { int have_xff_ip = 0; char buffer[XFF_MAXLEN]; if (FlowGetAppProtocol(p->flow) == ALPROTO_HTTP) { if (pa->flags & PACKET_ALERT_FLAG_TX) { have_xff_ip = HttpXFFGetIPFromTx(p, pa->tx_id, xff_cfg, buffer, XFF_MAXLEN); } else { have_xff_ip = HttpXFFGetIP(p, xff_cfg, buffer, XFF_MAXLEN); } } if (have_xff_ip) { if (xff_cfg->flags & XFF_EXTRADATA) { json_object_set_new(js, "xff", json_string(buffer)); } else if (xff_cfg->flags & XFF_OVERWRITE) { if (p->flowflags & FLOW_PKT_TOCLIENT) { json_object_set(js, "dest_ip", json_string(buffer)); } else { json_object_set(js, "src_ip", json_string(buffer)); } } } } OutputJSONBuffer(js, aft->file_ctx, &aft->json_buffer); json_object_del(js, "alert"); } json_object_clear(js); json_decref(js); if ((p->flags & PKT_HAS_TAG) && (json_output_ctx->flags & LOG_JSON_TAGGED_PACKETS)) { MemBufferReset(aft->json_buffer); json_t *packetjs = CreateJSONHeader((Packet *)p, 0, "packet"); if (unlikely(packetjs != NULL)) { AlertJsonPacket(p, packetjs); OutputJSONBuffer(packetjs, aft->file_ctx, &aft->json_buffer); json_decref(packetjs); } } return TM_ECODE_OK; }
/** * \brief Log the dropped packets in netfilter format when engine is running * in inline mode * * \param tv Pointer the current thread variables * \param p Pointer the packet which is being logged * * \return return TM_EODE_OK on success */ static int DropLogJSON (JsonDropLogThread *aft, const Packet *p) { JsonDropOutputCtx *drop_ctx = aft->drop_ctx; json_t *js = CreateJSONHeader(p, LOG_DIR_PACKET, "drop"); if (unlikely(js == NULL)) return TM_ECODE_OK; JsonAddCommonOptions(&drop_ctx->cfg, p, p->flow, js); json_t *djs = json_object(); if (unlikely(djs == NULL)) { json_decref(js); return TM_ECODE_OK; } /* reset */ MemBufferReset(aft->buffer); uint16_t proto = 0; if (PKT_IS_IPV4(p)) { json_object_set_new(djs, "len", json_integer(IPV4_GET_IPLEN(p))); json_object_set_new(djs, "tos", json_integer(IPV4_GET_IPTOS(p))); json_object_set_new(djs, "ttl", json_integer(IPV4_GET_IPTTL(p))); json_object_set_new(djs, "ipid", json_integer(IPV4_GET_IPID(p))); proto = IPV4_GET_IPPROTO(p); } else if (PKT_IS_IPV6(p)) { json_object_set_new(djs, "len", json_integer(IPV6_GET_PLEN(p))); json_object_set_new(djs, "tc", json_integer(IPV6_GET_CLASS(p))); json_object_set_new(djs, "hoplimit", json_integer(IPV6_GET_HLIM(p))); json_object_set_new(djs, "flowlbl", json_integer(IPV6_GET_FLOW(p))); proto = IPV6_GET_L4PROTO(p); } switch (proto) { case IPPROTO_TCP: if (PKT_IS_TCP(p)) { json_object_set_new(djs, "tcpseq", json_integer(TCP_GET_SEQ(p))); json_object_set_new(djs, "tcpack", json_integer(TCP_GET_ACK(p))); json_object_set_new(djs, "tcpwin", json_integer(TCP_GET_WINDOW(p))); json_object_set_new(djs, "syn", TCP_ISSET_FLAG_SYN(p) ? json_true() : json_false()); json_object_set_new(djs, "ack", TCP_ISSET_FLAG_ACK(p) ? json_true() : json_false()); json_object_set_new(djs, "psh", TCP_ISSET_FLAG_PUSH(p) ? json_true() : json_false()); json_object_set_new(djs, "rst", TCP_ISSET_FLAG_RST(p) ? json_true() : json_false()); json_object_set_new(djs, "urg", TCP_ISSET_FLAG_URG(p) ? json_true() : json_false()); json_object_set_new(djs, "fin", TCP_ISSET_FLAG_FIN(p) ? json_true() : json_false()); json_object_set_new(djs, "tcpres", json_integer(TCP_GET_RAW_X2(p->tcph))); json_object_set_new(djs, "tcpurgp", json_integer(TCP_GET_URG_POINTER(p))); } break; case IPPROTO_UDP: if (PKT_IS_UDP(p)) { json_object_set_new(djs, "udplen", json_integer(UDP_GET_LEN(p))); } break; case IPPROTO_ICMP: if (PKT_IS_ICMPV4(p)) { json_object_set_new(djs, "icmp_id", json_integer(ICMPV4_GET_ID(p))); json_object_set_new(djs, "icmp_seq", json_integer(ICMPV4_GET_SEQ(p))); } else if(PKT_IS_ICMPV6(p)) { json_object_set_new(djs, "icmp_id", json_integer(ICMPV6_GET_ID(p))); json_object_set_new(djs, "icmp_seq", json_integer(ICMPV6_GET_SEQ(p))); } break; } json_object_set_new(js, "drop", djs); if (aft->drop_ctx->flags & LOG_DROP_ALERTS) { int logged = 0; int i; for (i = 0; i < p->alerts.cnt; i++) { const PacketAlert *pa = &p->alerts.alerts[i]; if (unlikely(pa->s == NULL)) { continue; } if ((pa->action & (ACTION_REJECT|ACTION_REJECT_DST|ACTION_REJECT_BOTH)) || ((pa->action & ACTION_DROP) && EngineModeIsIPS())) { AlertJsonHeader(NULL, p, pa, js, 0); logged = 1; } } if (logged == 0) { if (p->alerts.drop.action != 0) { const PacketAlert *pa = &p->alerts.drop; AlertJsonHeader(NULL, p, pa, js, 0); } } } OutputJSONBuffer(js, aft->drop_ctx->file_ctx, &aft->buffer); json_object_del(js, "drop"); json_object_clear(js); json_decref(js); return TM_ECODE_OK; }