From: Jason Ish Date: Mon, 11 Dec 2017 16:16:47 +0000 (-0600) Subject: eve: top level metadata object X-Git-Tag: suricata-4.1.0-beta1~269 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5138f99c580e75d38e0e6cf38253d16e84a374d9;p=thirdparty%2Fsuricata.git eve: top level metadata object Contains: - flowbits (as array) - flowints (map) - flowvars (map) - pktvars (map) --- diff --git a/src/output-json.c b/src/output-json.c index 4d2fe5e572..26bd123e99 100644 --- a/src/output-json.c +++ b/src/output-json.c @@ -154,6 +154,111 @@ static void JsonAddPacketvars(const Packet *p, json_t *js_vars) } } +/** + * \brief "New" Add flow variables to a json object. + * + * Adds "flowvars" (map), "flowints" (map) and "flowbits" (array) to + * the json object provided as js_root. + * + * This is the "new" method for doing this as flowbits is an array of + * strings instead of a map of boolean values. + */ +static void JsonAddFlowVars(const Flow *f, json_t *js_root) +{ + if (f == NULL || f->flowvar == NULL) { + return; + } + json_t *js_flowvars = 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_object(); + 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_object_set_new(js_flowvars, varname, + json_string((char *)printable_buf)); + } + } else if (fv->datatype == FLOWVAR_TYPE_STR && fv->key != NULL) { + if (js_flowvars == NULL) { + js_flowvars = json_object(); + 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_object_set_new(js_flowvars, (const char *)keybuf, + json_string((char *)printable_buf)); + + } 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 (js_flowbits == NULL) { + js_flowbits = json_array(); + if (js_flowbits == NULL) + break; + } + json_array_append(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); + } +} + static void JsonAddFlowvars(const Flow *f, json_t *js_vars) { if (f == NULL || f->flowvar == NULL) { @@ -263,6 +368,26 @@ void JsonAddVars(const Packet *p, const Flow *f, json_t *js) } } +/** + * \brief Add top-level metadata to the eve json object. + */ +static void JsonAddMetadata(const Packet *p, const Flow *f, json_t *js) +{ + if ((p && p->pktvar) || (f && f->flowvar)) { + json_t *js_vars = json_object(); + if (js_vars) { + if (f && f->flowvar) { + JsonAddFlowVars(f, js_vars); + } + if (p && p->pktvar) { + JsonAddPacketvars(p, js_vars); + } + + json_object_set_new(js, "metadata", js_vars); + } + } +} + /** \brief jsonify tcp flags field * Only add 'true' fields in an attempt to keep things reasonably compact. */ @@ -396,6 +521,7 @@ json_t *CreateJSONHeader(const Packet *p, int direction_sensitive, const char *event_type) { char timebuf[64]; + const Flow *f = (const Flow *)p->flow; json_t *js = json_object(); if (unlikely(js == NULL)) @@ -406,7 +532,7 @@ json_t *CreateJSONHeader(const Packet *p, int direction_sensitive, /* time & tx */ json_object_set_new(js, "timestamp", json_string(timebuf)); - CreateJSONFlowId(js, (const Flow *)p->flow); + CreateJSONFlowId(js, f); /* sensor id */ if (sensor_id >= 0) @@ -453,6 +579,9 @@ json_t *CreateJSONHeader(const Packet *p, int direction_sensitive, /* 5-tuple */ JsonFiveTuple(p, direction_sensitive, js); + /* Metadata. */ + JsonAddMetadata(p, f, js); + /* icmp */ switch (p->proto) { case IPPROTO_ICMP: