From: Maurizio Abba Date: Thu, 26 Jul 2018 12:54:58 +0000 (+0100) Subject: output-json: ensure string is json-encodable X-Git-Tag: suricata-4.1.0-rc2~167 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bf4398b15d4244a51800ece59566babd2be1fa05;p=thirdparty%2Fsuricata.git output-json: ensure string is json-encodable Substitute json_string with SCJsonString custom function. SCJsonString will ensure string passed is json-encodable (utf-8). If it's not, the string will be converted in such a way that any non-printable character will be encoded in its hex form. The resulting json object will be returned. rust modification will encode any non-printable character during its conversion in to_cstring. --- diff --git a/rust/src/json.rs b/rust/src/json.rs index 38ebda3507..853c6e241d 100644 --- a/rust/src/json.rs +++ b/rust/src/json.rs @@ -139,7 +139,7 @@ impl Json { fn to_cstring(val: &[u8]) -> CString { let mut safe = Vec::with_capacity(val.len()); for c in val { - if *c == 0 || *c > 0x7f { + if *c < 0x20 || *c > 0x7e { safe.extend(format!("\\x{:02x}", *c).as_bytes()); } else { safe.push(*c); diff --git a/src/output-json-alert.c b/src/output-json-alert.c index 008a5441eb..6a7aed45f0 100644 --- a/src/output-json-alert.c +++ b/src/output-json-alert.c @@ -328,9 +328,9 @@ void AlertJsonHeader(void *ctx, const Packet *p, const PacketAlert *pa, json_t * 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 : "")); + SCJsonString((pa->s->msg) ? pa->s->msg : "")); json_object_set_new(ajs, "category", - json_string((pa->s->class_msg) ? pa->s->class_msg : "")); + SCJsonString((pa->s->class_msg) ? pa->s->class_msg : "")); json_object_set_new(ajs, "severity", json_integer(pa->s->prio)); if (p->tenant_id > 0) diff --git a/src/output-json-dnp3-objects.c b/src/output-json-dnp3-objects.c index ff57dfcf65..2d44aaf0ea 100644 --- a/src/output-json-dnp3-objects.c +++ b/src/output-json-dnp3-objects.c @@ -29,6 +29,7 @@ #include "app-layer-dnp3.h" #include "app-layer-dnp3-objects.h" #include "output-json-dnp3-objects.h" +#include "output-json.h" #ifdef HAVE_LIBJANSSON @@ -2133,7 +2134,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->filename_size + 1]; memcpy(tmpbuf, data->filename, data->filename_size); tmpbuf[data->filename_size] = '\0'; - json_object_set_new(js, "filename", json_string(tmpbuf)); + json_object_set_new(js, "filename", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "filename", json_string("")); } @@ -2145,7 +2146,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->data_size + 1]; memcpy(tmpbuf, data->data, data->data_size); tmpbuf[data->data_size] = '\0'; - json_object_set_new(js, "data", json_string(tmpbuf)); + json_object_set_new(js, "data", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "data", json_string("")); } @@ -2169,7 +2170,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->username_size + 1]; memcpy(tmpbuf, data->username, data->username_size); tmpbuf[data->username_size] = '\0'; - json_object_set_new(js, "username", json_string(tmpbuf)); + json_object_set_new(js, "username", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "username", json_string("")); } @@ -2179,7 +2180,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->password_size + 1]; memcpy(tmpbuf, data->password, data->password_size); tmpbuf[data->password_size] = '\0'; - json_object_set_new(js, "password", json_string(tmpbuf)); + json_object_set_new(js, "password", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "password", json_string("")); } @@ -2211,7 +2212,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->filename_size + 1]; memcpy(tmpbuf, data->filename, data->filename_size); tmpbuf[data->filename_size] = '\0'; - json_object_set_new(js, "filename", json_string(tmpbuf)); + json_object_set_new(js, "filename", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "filename", json_string("")); } @@ -2235,7 +2236,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->optional_text_len + 1]; memcpy(tmpbuf, data->optional_text, data->optional_text_len); tmpbuf[data->optional_text_len] = '\0'; - json_object_set_new(js, "optional_text", json_string(tmpbuf)); + json_object_set_new(js, "optional_text", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "optional_text", json_string("")); } @@ -2253,7 +2254,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->file_data_len + 1]; memcpy(tmpbuf, data->file_data, data->file_data_len); tmpbuf[data->file_data_len] = '\0'; - json_object_set_new(js, "file_data", json_string(tmpbuf)); + json_object_set_new(js, "file_data", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "file_data", json_string("")); } @@ -2273,7 +2274,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->optional_text_len + 1]; memcpy(tmpbuf, data->optional_text, data->optional_text_len); tmpbuf[data->optional_text_len] = '\0'; - json_object_set_new(js, "optional_text", json_string(tmpbuf)); + json_object_set_new(js, "optional_text", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "optional_text", json_string("")); } @@ -2301,7 +2302,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->filename_size + 1]; memcpy(tmpbuf, data->filename, data->filename_size); tmpbuf[data->filename_size] = '\0'; - json_object_set_new(js, "filename", json_string(tmpbuf)); + json_object_set_new(js, "filename", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "filename", json_string("")); } @@ -2315,7 +2316,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->file_specification_len + 1]; memcpy(tmpbuf, data->file_specification, data->file_specification_len); tmpbuf[data->file_specification_len] = '\0'; - json_object_set_new(js, "file_specification", json_string(tmpbuf)); + json_object_set_new(js, "file_specification", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "file_specification", json_string("")); } @@ -2341,7 +2342,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, } case DNP3_OBJECT_CODE(83, 1): { DNP3ObjectG83V1 *data = point->data; - json_object_set_new(js, "data->vendor_code", json_string(data->vendor_code)); + json_object_set_new(js, "data->vendor_code", SCJsonString(data->vendor_code)); json_object_set_new(js, "object_id", json_integer(data->object_id)); json_object_set_new(js, "length", @@ -2486,7 +2487,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->error_text_len + 1]; memcpy(tmpbuf, data->error_text, data->error_text_len); tmpbuf[data->error_text_len] = '\0'; - json_object_set_new(js, "error_text", json_string(tmpbuf)); + json_object_set_new(js, "error_text", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "error_text", json_string("")); } @@ -2540,7 +2541,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->username_len + 1]; memcpy(tmpbuf, data->username, data->username_len); tmpbuf[data->username_len] = '\0'; - json_object_set_new(js, "username", json_string(tmpbuf)); + json_object_set_new(js, "username", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "username", json_string("")); } @@ -2572,7 +2573,7 @@ void OutputJsonDNP3SetItem(json_t *js, DNP3Object *object, char tmpbuf[data->username_len + 1]; memcpy(tmpbuf, data->username, data->username_len); tmpbuf[data->username_len] = '\0'; - json_object_set_new(js, "username", json_string(tmpbuf)); + json_object_set_new(js, "username", SCJsonString(tmpbuf)); } else { json_object_set_new(js, "username", json_string("")); } diff --git a/src/output-json-dns.c b/src/output-json-dns.c index e21f7d59fd..b79cc68ef3 100644 --- a/src/output-json-dns.c +++ b/src/output-json-dns.c @@ -429,7 +429,7 @@ static json_t *OutputQuery(DNSTransaction *tx, uint64_t tx_id, DNSQueryEntry *en char *c; c = BytesToString((uint8_t *)((uint8_t *)entry + sizeof(DNSQueryEntry)), entry->len); if (c != NULL) { - json_object_set_new(djs, "rrname", json_string(c)); + json_object_set_new(djs, "rrname", SCJsonString(c)); SCFree(c); } @@ -766,7 +766,7 @@ static void OutputAnswerV1(LogDnsLogThread *aft, json_t *djs, c = BytesToString((uint8_t *)((uint8_t *)entry + sizeof(DNSAnswerEntry)), entry->fqdn_len); if (c != NULL) { - json_object_set_new(js, "rrname", json_string(c)); + json_object_set_new(js, "rrname", SCJsonString(c)); SCFree(c); } } @@ -799,7 +799,7 @@ static void OutputAnswerV1(LogDnsLogThread *aft, json_t *djs, entry->data_len : sizeof(buffer) - 1; memcpy(buffer, ptr, copy_len); buffer[copy_len] = '\0'; - json_object_set_new(js, "rdata", json_string(buffer)); + json_object_set_new(js, "rdata", SCJsonString(buffer)); } else { json_object_set_new(js, "rdata", json_string("")); } @@ -959,7 +959,7 @@ static void OutputFailure(LogDnsLogThread *aft, json_t *djs, char *c; c = BytesToString((uint8_t *)((uint8_t *)entry + sizeof(DNSQueryEntry)), entry->len); if (c != NULL) { - json_object_set_new(js, "rrname", json_string(c)); + json_object_set_new(js, "rrname", SCJsonString(c)); SCFree(c); } diff --git a/src/output-json-email-common.c b/src/output-json-email-common.c index e4055061be..85ae62331b 100644 --- a/src/output-json-email-common.c +++ b/src/output-json-email-common.c @@ -114,10 +114,10 @@ static json_t* JsonEmailJsonArrayFromCommaList(const uint8_t *val, size_t len) return NULL; } sp = SkipWhiteSpaceTill(p, savep); - json_array_append_new(ajs, json_string(sp)); + json_array_append_new(ajs, SCJsonString(sp)); while ((p = strtok_r(NULL, ",", &savep)) != NULL) { sp = SkipWhiteSpaceTill(p, savep); - json_array_append_new(ajs, json_string(sp)); + json_array_append_new(ajs, SCJsonString(sp)); } } else { json_decref(ajs); @@ -180,7 +180,7 @@ static int JsonEmailAddToJsonArray(const uint8_t *val, size_t len, void *data) if (ajs == NULL) return 0; char *value = BytesToString((uint8_t *)val, len); - json_array_append_new(ajs, json_string(value)); + json_array_append_new(ajs, SCJsonString(value)); SCFree(value); return 1; } @@ -223,7 +223,7 @@ static void JsonEmailLogJSONCustom(OutputJsonEmailCtx *email_ctx, json_t *js, SM char *s = BytesToString((uint8_t *)field->value, (size_t)field->value_len); if (likely(s != NULL)) { - json_object_set_new(js, email_fields[f].config_field, json_string(s)); + json_object_set_new(js, email_fields[f].config_field, SCJsonString(s)); SCFree(s); } } @@ -285,7 +285,7 @@ static json_t *JsonEmailLogJsonData(const Flow *f, void *state, void *vtx, uint6 if (likely(s != NULL)) { //printf("From: \"%s\"\n", s); char * sp = SkipWhiteSpaceTill(s, s + strlen(s)); - json_object_set_new(sjs, "from", json_string(sp)); + json_object_set_new(sjs, "from", SCJsonString(sp)); SCFree(s); } } @@ -325,7 +325,7 @@ static json_t *JsonEmailLogJsonData(const Flow *f, void *state, void *vtx, uint6 (size_t)url->url_len); if (s != NULL) { json_array_append_new(js_url, - json_string(s)); + SCJsonString(s)); SCFree(s); url_cnt += 1; } @@ -337,7 +337,7 @@ static json_t *JsonEmailLogJsonData(const Flow *f, void *state, void *vtx, uint6 char *s = BytesToString((uint8_t *)entity->filename, (size_t)entity->filename_len); json_array_append_new(js_attch, - json_string(s)); + SCJsonString(s)); SCFree(s); attch_cnt += 1; } @@ -348,7 +348,7 @@ static json_t *JsonEmailLogJsonData(const Flow *f, void *state, void *vtx, uint6 (size_t)url->url_len); if (s != NULL) { json_array_append_new(js_url, - json_string(s)); + SCJsonString(s)); SCFree(s); url_cnt += 1; } diff --git a/src/output-json-file.c b/src/output-json-file.c index 29e70a7b55..3a90f1a040 100644 --- a/src/output-json-file.c +++ b/src/output-json-file.c @@ -146,7 +146,7 @@ json_t *JsonBuildFileInfoRecord(const Packet *p, const File *ff, } char *s = BytesToString(ff->name, ff->name_len); - json_object_set_new(fjs, "filename", json_string(s)); + json_object_set_new(fjs, "filename", SCJsonString(s)); if (s != NULL) SCFree(s); #ifdef HAVE_MAGIC diff --git a/src/output-json-http.c b/src/output-json-http.c index 3c1560cfdc..17962de9b0 100644 --- a/src/output-json-http.c +++ b/src/output-json-http.c @@ -197,7 +197,7 @@ static void JsonHttpLogJSONBasic(json_t *js, htp_tx_t *tx) { c = bstr_util_strdup_to_c(tx->request_hostname); if (c != NULL) { - json_object_set_new(js, "hostname", json_string(c)); + json_object_set_new(js, "hostname", SCJsonString(c)); SCFree(c); } } @@ -207,7 +207,7 @@ static void JsonHttpLogJSONBasic(json_t *js, htp_tx_t *tx) { c = bstr_util_strdup_to_c(tx->request_uri); if (c != NULL) { - json_object_set_new(js, "url", json_string(c)); + json_object_set_new(js, "url", SCJsonString(c)); SCFree(c); } } @@ -220,7 +220,7 @@ static void JsonHttpLogJSONBasic(json_t *js, htp_tx_t *tx) if (h_user_agent != NULL) { c = bstr_util_strdup_to_c(h_user_agent->value); if (c != NULL) { - json_object_set_new(js, "http_user_agent", json_string(c)); + json_object_set_new(js, "http_user_agent", SCJsonString(c)); SCFree(c); } } @@ -250,7 +250,7 @@ static void JsonHttpLogJSONBasic(json_t *js, htp_tx_t *tx) p = strchr(c, ';'); if (p != NULL) *p = '\0'; - json_object_set_new(js, "http_content_type", json_string(c)); + json_object_set_new(js, "http_content_type", SCJsonString(c)); SCFree(c); } } @@ -289,7 +289,7 @@ static void JsonHttpLogJSONCustom(LogHttpFileCtx *http_ctx, json_t *js, htp_tx_t if (c != NULL) { json_object_set_new(js, http_fields[f].config_field, - json_string(c)); + SCJsonString(c)); SCFree(c); } } @@ -310,7 +310,7 @@ static void JsonHttpLogJSONExtended(json_t *js, htp_tx_t *tx) if (h_referer != NULL) { c = bstr_util_strdup_to_c(h_referer->value); if (c != NULL) { - json_object_set_new(js, "http_refer", json_string(c)); + json_object_set_new(js, "http_refer", SCJsonString(c)); SCFree(c); } } @@ -319,7 +319,7 @@ static void JsonHttpLogJSONExtended(json_t *js, htp_tx_t *tx) if (tx->request_method != NULL) { c = bstr_util_strdup_to_c(tx->request_method); if (c != NULL) { - json_object_set_new(js, "http_method", json_string(c)); + json_object_set_new(js, "http_method", SCJsonString(c)); SCFree(c); } } @@ -328,7 +328,7 @@ static void JsonHttpLogJSONExtended(json_t *js, htp_tx_t *tx) if (tx->request_protocol != NULL) { c = bstr_util_strdup_to_c(tx->request_protocol); if (c != NULL) { - json_object_set_new(js, "protocol", json_string(c)); + json_object_set_new(js, "protocol", SCJsonString(c)); SCFree(c); } } @@ -346,7 +346,7 @@ static void JsonHttpLogJSONExtended(json_t *js, htp_tx_t *tx) if (h_location != NULL) { c = bstr_util_strdup_to_c(h_location->value); if (c != NULL) { - json_object_set_new(js, "redirect", json_string(c)); + json_object_set_new(js, "redirect", SCJsonString(c)); SCFree(c); } } diff --git a/src/output-json-smtp.c b/src/output-json-smtp.c index eb7cd283de..451ed450dc 100644 --- a/src/output-json-smtp.c +++ b/src/output-json-smtp.c @@ -64,17 +64,17 @@ static json_t *JsonSmtpDataLogger(const Flow *f, void *state, void *vtx, uint64_ } if (((SMTPState *)state)->helo) { json_object_set_new(sjs, "helo", - json_string((const char *)((SMTPState *)state)->helo)); + SCJsonString((const char *)((SMTPState *)state)->helo)); } if (tx->mail_from) { json_object_set_new(sjs, "mail_from", - json_string((const char *)tx->mail_from)); + SCJsonString((const char *)tx->mail_from)); } if (!TAILQ_EMPTY(&tx->rcpt_to_list)) { json_t *js_rcptto = json_array(); if (likely(js_rcptto != NULL)) { TAILQ_FOREACH(rcptto_str, &tx->rcpt_to_list, next) { - json_array_append_new(js_rcptto, json_string((char *)rcptto_str->str)); + json_array_append_new(js_rcptto, SCJsonString((char *)rcptto_str->str)); } json_object_set_new(sjs, "rcpt_to", js_rcptto); } diff --git a/src/output-json-ssh.c b/src/output-json-ssh.c index 20b0191517..7563f42c1a 100644 --- a/src/output-json-ssh.c +++ b/src/output-json-ssh.c @@ -72,20 +72,20 @@ void JsonSshLogJSON(json_t *tjs, SshState *ssh_state) json_t *cjs = json_object(); if (cjs != NULL) { json_object_set_new(cjs, "proto_version", - json_string((char *)ssh_state->cli_hdr.proto_version)); + SCJsonString((char *)ssh_state->cli_hdr.proto_version)); json_object_set_new(cjs, "software_version", - json_string((char *)ssh_state->cli_hdr.software_version)); + SCJsonString((char *)ssh_state->cli_hdr.software_version)); } json_object_set_new(tjs, "client", cjs); json_t *sjs = json_object(); if (sjs != NULL) { json_object_set_new(sjs, "proto_version", - json_string((char *)ssh_state->srv_hdr.proto_version)); + SCJsonString((char *)ssh_state->srv_hdr.proto_version)); json_object_set_new(sjs, "software_version", - json_string((char *)ssh_state->srv_hdr.software_version)); + SCJsonString((char *)ssh_state->srv_hdr.software_version)); } json_object_set_new(tjs, "server", sjs); diff --git a/src/output-json-tls.c b/src/output-json-tls.c index fbe46ce459..bed799fce0 100644 --- a/src/output-json-tls.c +++ b/src/output-json-tls.c @@ -118,7 +118,7 @@ static void JsonTlsLogSubject(json_t *js, SSLState *ssl_state) { if (ssl_state->server_connp.cert0_subject) { json_object_set_new(js, "subject", - json_string(ssl_state->server_connp.cert0_subject)); + SCJsonString(ssl_state->server_connp.cert0_subject)); } } @@ -126,7 +126,7 @@ static void JsonTlsLogIssuer(json_t *js, SSLState *ssl_state) { if (ssl_state->server_connp.cert0_issuerdn) { json_object_set_new(js, "issuerdn", - json_string(ssl_state->server_connp.cert0_issuerdn)); + SCJsonString(ssl_state->server_connp.cert0_issuerdn)); } } @@ -141,7 +141,7 @@ static void JsonTlsLogFingerprint(json_t *js, SSLState *ssl_state) { if (ssl_state->server_connp.cert0_fingerprint) { json_object_set_new(js, "fingerprint", - json_string(ssl_state->server_connp.cert0_fingerprint)); + SCJsonString(ssl_state->server_connp.cert0_fingerprint)); } } @@ -149,7 +149,7 @@ static void JsonTlsLogSni(json_t *js, SSLState *ssl_state) { if (ssl_state->client_connp.sni) { json_object_set_new(js, "sni", - json_string(ssl_state->client_connp.sni)); + SCJsonString(ssl_state->client_connp.sni)); } } @@ -157,7 +157,7 @@ static void JsonTlsLogSerial(json_t *js, SSLState *ssl_state) { if (ssl_state->server_connp.cert0_serial) { json_object_set_new(js, "serial", - json_string(ssl_state->server_connp.cert0_serial)); + SCJsonString(ssl_state->server_connp.cert0_serial)); } } diff --git a/src/output-json.c b/src/output-json.c index 485ea58517..55539b96ae 100644 --- a/src/output-json.c +++ b/src/output-json.c @@ -87,6 +87,7 @@ void OutputJsonRegister (void) #define MODULE_NAME "OutputJSON" #define OUTPUT_BUFFER_SIZE 65536 +#define MAX_JSON_SIZE 2048 static void OutputJsonDeInitCtx(OutputCtx *); @@ -117,6 +118,31 @@ void SCJsonDecref(json_t *json) json_decref(json); } +json_t *SCJsonString(const char *val) +{ + if (val == NULL){ + return NULL; + } + json_t * retval = json_string(val); + char retbuf[MAX_JSON_SIZE] = {0}; + if (retval == NULL) { + uint32_t u = 0; + uint32_t offset = 0; + for (u = 0; u < strlen(val); u++) { + if (isprint(val[u])) { + PrintBufferData(retbuf, &offset, MAX_JSON_SIZE-1, "%c", + val[u]); + } else { + PrintBufferData(retbuf, &offset, MAX_JSON_SIZE-1, + "\\x%02X", val[u]); + } + } + retbuf[offset] = '\0'; + retval = json_string(retbuf); + } + return retval; +} + /* Default Sensor ID value */ static int64_t sensor_id = -1; /* -1 = not defined */ diff --git a/src/output-json.h b/src/output-json.h index 06d94df38d..e37f8b8f26 100644 --- a/src/output-json.h +++ b/src/output-json.h @@ -72,6 +72,7 @@ typedef struct OutputJsonCtx_ { } OutputJsonCtx; json_t *SCJsonBool(int val); +json_t *SCJsonString(const char *val); void SCJsonDecref(json_t *js); #endif /* HAVE_LIBJANSSON */ diff --git a/src/runmode-unix-socket.c b/src/runmode-unix-socket.c index 21b2e23c6f..199dbee75d 100644 --- a/src/runmode-unix-socket.c +++ b/src/runmode-unix-socket.c @@ -21,6 +21,7 @@ #include "runmodes.h" #include "runmode-pcap-file.h" #include "output.h" +#include "output-json.h" #include "util-debug.h" #include "util-time.h" @@ -163,7 +164,7 @@ static TmEcode UnixSocketPcapFilesList(json_t *cmd, json_t* answer, void *data) return TM_ECODE_FAILED; } TAILQ_FOREACH(file, &this->files, next) { - json_array_append_new(jarray, json_string(file->filename)); + json_array_append_new(jarray, SCJsonString(file->filename)); i++; } json_object_set_new(jdata, "count", json_integer(i));