Example #1
0
static void JsonAddPacketvars(const Packet *p, json_t *js_vars)
{
    if (p == NULL || p->pktvar == NULL) {
        return;
    }
    json_t *js_pktvars = NULL;
    PktVar *pv = p->pktvar;
    while (pv != NULL) {
        if (pv->key || pv->id > 0) {
            if (js_pktvars == NULL) {
                js_pktvars = json_array();
                if (js_pktvars == NULL)
                    break;
            }
            json_t *js_pair = json_object();
            if (js_pair == NULL) {
                break;
            }

            if (pv->key != NULL) {
                uint32_t offset = 0;
                uint8_t keybuf[pv->key_len + 1];
                PrintStringsToBuffer(keybuf, &offset,
                        sizeof(keybuf),
                        pv->key, pv->key_len);
                uint32_t len = pv->value_len;
                uint8_t printable_buf[len + 1];
                offset = 0;
                PrintStringsToBuffer(printable_buf, &offset,
                        sizeof(printable_buf),
                        pv->value, pv->value_len);
                json_object_set_new(js_pair, (char *)keybuf,
                        json_string((char *)printable_buf));
            } else {
                const char *varname = VarNameStoreLookupById(pv->id, VAR_TYPE_PKT_VAR);
                uint32_t len = pv->value_len;
                uint8_t printable_buf[len + 1];
                uint32_t offset = 0;
                PrintStringsToBuffer(printable_buf, &offset,
                        sizeof(printable_buf),
                        pv->value, pv->value_len);

                json_object_set_new(js_pair, varname,
                        json_string((char *)printable_buf));
            }
            json_array_append_new(js_pktvars, js_pair);
        }
        pv = pv->next;
    }
    if (js_pktvars) {
        json_object_set_new(js_vars, "pktvars", js_pktvars);
    }
}
Example #2
0
/* 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;
}
Example #3
0
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;
}
Example #4
0
/** Handle the case where no JSON support is compiled in.
 *
 */
static int AlertJson(ThreadVars *tv, JsonAlertLogThread *aft, const Packet *p)
{
    MemBuffer *payload = aft->payload_buffer;

    int i;

    if (p->alerts.cnt == 0)
        return TM_ECODE_OK;

    MemBufferReset(aft->json_buffer);

    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;
        }

        char *action = "allowed";
        if (pa->action & (ACTION_REJECT|ACTION_REJECT_DST|ACTION_REJECT_BOTH)) {
            action = "blocked";
        } else if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) {
            action = "blocked";
        }

        json_t *ajs = json_object();
        if (ajs == NULL) {
            json_decref(js);
            return TM_ECODE_OK;
        }

        json_object_set_new(ajs, "action", json_string(action));
        json_object_set_new(ajs, "gid", json_integer(pa->s->gid));
        json_object_set_new(ajs, "signature_id", json_integer(pa->s->id));
        json_object_set_new(ajs, "rev", json_integer(pa->s->rev));
        json_object_set_new(ajs, "signature",
                            json_string((pa->s->msg) ? pa->s->msg : ""));
        json_object_set_new(ajs, "category",
                            json_string((pa->s->class_msg) ? pa->s->class_msg : ""));
        json_object_set_new(ajs, "severity", json_integer(pa->s->prio));

        /* alert */
        json_object_set_new(js, "alert", ajs);

        /* payload */
        if (aft->file_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,
                                    AlertJsonPrintStreamSegmentCallback,
                                    (void *)payload);

                if (aft->file_ctx->flags & LOG_JSON_PAYLOAD_BASE64) {
                    unsigned long len = JSON_STREAM_BUFFER_SIZE * 2;
                    unsigned char encoded[len];
                    Base64Encode((unsigned char *)payload, payload->offset, encoded, &len);
                    json_object_set_new(js, "payload", json_string((char *)encoded));
                }

                if (aft->file_ctx->flags & LOG_JSON_PAYLOAD) {
                    json_object_set_new(js, "payload_printable",
                                        json_string((char *)payload->buffer));
                }
            } else {
                /* This is a single packet and not a stream */
                unsigned char packet_buf[p->payload_len + 1];
                uint32_t offset = 0;

                PrintStringsToBuffer(packet_buf, &offset,
                                     p->payload_len + 1,
                                     p->payload, p->payload_len);

                if (aft->file_ctx->flags & LOG_JSON_PAYLOAD_BASE64) {
                    unsigned long len = sizeof(packet_buf) * 2;
                    unsigned char encoded[len];
                    Base64Encode(packet_buf, offset, encoded, &len);
                    json_object_set_new(js, "payload", json_string((char *)encoded));
                }

                if (aft->file_ctx->flags & LOG_JSON_PAYLOAD) {
                    json_object_set_new(js, "payload_printable", json_string((char *)packet_buf));
                }
            }

            json_object_set_new(js, "stream", json_integer(stream));
        }

        /* 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->json_buffer);
        json_object_del(js, "alert");
    }
    json_object_clear(js);
    json_decref(js);

    return TM_ECODE_OK;
}
Example #5
0
/**
 * \brief Add flow variables to a json object.
 *
 * Adds "flowvars" (map), "flowints" (map) and "flowbits" (array) to
 * the json object provided as js_root.
 */
static void JsonAddFlowVars(const Flow *f, json_t *js_root, json_t **js_traffic)
{
    if (f == NULL || f->flowvar == NULL) {
        return;
    }
    json_t *js_flowvars = NULL;
    json_t *js_traffic_id = NULL;
    json_t *js_traffic_label = NULL;
    json_t *js_flowints = NULL;
    json_t *js_flowbits = NULL;
    GenericVar *gv = f->flowvar;
    while (gv != NULL) {
        if (gv->type == DETECT_FLOWVAR || gv->type == DETECT_FLOWINT) {
            FlowVar *fv = (FlowVar *)gv;
            if (fv->datatype == FLOWVAR_TYPE_STR && fv->key == NULL) {
                const char *varname = VarNameStoreLookupById(fv->idx,
                        VAR_TYPE_FLOW_VAR);
                if (varname) {
                    if (js_flowvars == NULL) {
                        js_flowvars = json_array();
                        if (js_flowvars == NULL)
                            break;
                    }

                    uint32_t len = fv->data.fv_str.value_len;
                    uint8_t printable_buf[len + 1];
                    uint32_t offset = 0;
                    PrintStringsToBuffer(printable_buf, &offset,
                            sizeof(printable_buf),
                            fv->data.fv_str.value, fv->data.fv_str.value_len);

                    json_t *js_flowvar = json_object();
                    if (unlikely(js_flowvar == NULL)) {
                        break;
                    }
                    json_object_set_new(js_flowvar, varname,
                            json_string((char *)printable_buf));
                    json_array_append_new(js_flowvars, js_flowvar);
                }
            } else if (fv->datatype == FLOWVAR_TYPE_STR && fv->key != NULL) {
                if (js_flowvars == NULL) {
                    js_flowvars = json_array();
                    if (js_flowvars == NULL)
                        break;
                }

                uint8_t keybuf[fv->keylen + 1];
                uint32_t offset = 0;
                PrintStringsToBuffer(keybuf, &offset,
                        sizeof(keybuf),
                        fv->key, fv->keylen);

                uint32_t len = fv->data.fv_str.value_len;
                uint8_t printable_buf[len + 1];
                offset = 0;
                PrintStringsToBuffer(printable_buf, &offset,
                        sizeof(printable_buf),
                        fv->data.fv_str.value, fv->data.fv_str.value_len);

                json_t *js_flowvar = json_object();
                if (unlikely(js_flowvar == NULL)) {
                    break;
                }
                json_object_set_new(js_flowvar, (const char *)keybuf,
                        json_string((char *)printable_buf));
                json_array_append_new(js_flowvars, js_flowvar);
            } else if (fv->datatype == FLOWVAR_TYPE_INT) {
                const char *varname = VarNameStoreLookupById(fv->idx,
                        VAR_TYPE_FLOW_INT);
                if (varname) {
                    if (js_flowints == NULL) {
                        js_flowints = json_object();
                        if (js_flowints == NULL)
                            break;
                    }

                    json_object_set_new(js_flowints, varname,
                            json_integer(fv->data.fv_int.value));
                }

            }
        } else if (gv->type == DETECT_FLOWBITS) {
            FlowBit *fb = (FlowBit *)gv;
            const char *varname = VarNameStoreLookupById(fb->idx,
                    VAR_TYPE_FLOW_BIT);
            if (varname) {
                if (SCStringHasPrefix(varname, TRAFFIC_ID_PREFIX)) {
                    if (js_traffic_id == NULL) {
                        js_traffic_id = json_array();
                        if (unlikely(js_traffic_id == NULL)) {
                            break;
                        }
                    }
                    json_array_append_new(js_traffic_id,
                            json_string(&varname[traffic_id_prefix_len]));
                } else if (SCStringHasPrefix(varname, TRAFFIC_LABEL_PREFIX)) {
                    if (js_traffic_label == NULL) {
                        js_traffic_label = json_array();
                        if (unlikely(js_traffic_label == NULL)) {
                            break;
                        }
                    }
                    json_array_append_new(js_traffic_label,
                            json_string(&varname[traffic_label_prefix_len]));
                } else {
                    if (js_flowbits == NULL) {
                        js_flowbits = json_array();
                        if (unlikely(js_flowbits == NULL))
                            break;
                    }
                    json_array_append_new(js_flowbits, json_string(varname));
                }
            }
        }
        gv = gv->next;
    }
    if (js_flowbits) {
        json_object_set_new(js_root, "flowbits", js_flowbits);
    }
    if (js_flowints) {
        json_object_set_new(js_root, "flowints", js_flowints);
    }
    if (js_flowvars) {
        json_object_set_new(js_root, "flowvars", js_flowvars);
    }

    if (js_traffic_id != NULL || js_traffic_label != NULL) {
        *js_traffic = json_object();
        if (likely(*js_traffic != NULL)) {
            if (js_traffic_id != NULL) {
                json_object_set_new(*js_traffic, "id", js_traffic_id);
            }
            if (js_traffic_label != NULL) {
                json_object_set_new(*js_traffic, "label", js_traffic_label);
            }
        }
    }
}