From: Mats Klepsland Date: Fri, 13 Jan 2017 11:20:34 +0000 (+0100) Subject: output-json-tls: log certificate and chain X-Git-Tag: suricata-4.0.0-beta1~292 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=115b3138cc4723090774f68ac5a43fb91bd971ab;p=thirdparty%2Fsuricata.git output-json-tls: log certificate and chain Log entire certificate and certificate chain Base64 encoded. --- diff --git a/src/output-json-tls.c b/src/output-json-tls.c index 485defc4b9..2ef4ef714d 100644 --- a/src/output-json-tls.c +++ b/src/output-json-tls.c @@ -66,6 +66,8 @@ SC_ATOMIC_DECLARE(unsigned int, cert_id); #define LOG_TLS_FIELD_NOTBEFORE (1 << 4) #define LOG_TLS_FIELD_NOTAFTER (1 << 5) #define LOG_TLS_FIELD_SNI (1 << 6) +#define LOG_TLS_FIELD_CERTIFICATE (1 << 7) +#define LOG_TLS_FIELD_CHAIN (1 << 8) typedef struct { char *name; @@ -80,6 +82,8 @@ TlsFields tls_fields[] = { { "not_before", LOG_TLS_FIELD_NOTBEFORE }, { "not_after", LOG_TLS_FIELD_NOTAFTER }, { "sni", LOG_TLS_FIELD_SNI }, + { "certificate", LOG_TLS_FIELD_CERTIFICATE }, + { "chain", LOG_TLS_FIELD_CHAIN }, { NULL, -1 } }; @@ -178,6 +182,51 @@ static void JsonTlsLogNotAfter(json_t *js, SSLState *ssl_state) } } +static void JsonTlsLogCertificate(json_t *js, SSLState *ssl_state) +{ + if ((ssl_state->server_connp.cert_input == NULL) || + (ssl_state->server_connp.cert_input_len == 0)) { + return; + } + + SSLCertsChain *cert = TAILQ_FIRST(&ssl_state->server_connp.certs); + if (cert == NULL) { + return; + } + + unsigned long len = cert->cert_len * 2; + uint8_t encoded[len]; + if (Base64Encode(cert->cert_data, cert->cert_len, encoded, &len) == + SC_BASE64_OK) { + json_object_set_new(js, "certificate", json_string((char *)encoded)); + } +} + +static void JsonTlsLogChain(json_t *js, SSLState *ssl_state) +{ + if ((ssl_state->server_connp.cert_input == NULL) || + (ssl_state->server_connp.cert_input_len == 0)) { + return; + } + + json_t *chain = json_array(); + if (chain == NULL) { + return; + } + + SSLCertsChain *cert; + TAILQ_FOREACH(cert, &ssl_state->server_connp.certs, next) { + unsigned long len = cert->cert_len * 2; + uint8_t encoded[len]; + if (Base64Encode(cert->cert_data, cert->cert_len, encoded, &len) == + SC_BASE64_OK) { + json_array_append_new(chain, json_string((char *)encoded)); + } + } + + json_object_set_new(js, "chain", chain); +} + void JsonTlsLogJSONBasic(json_t *js, SSLState *ssl_state) { /* tls.subject */ @@ -217,6 +266,14 @@ static void JsonTlsLogJSONCustom(OutputTlsCtx *tls_ctx, json_t *js, /* tls.notafter */ if (tls_ctx->fields & LOG_TLS_FIELD_NOTAFTER) JsonTlsLogNotAfter(js, ssl_state); + + /* tls.certificate */ + if (tls_ctx->fields & LOG_TLS_FIELD_CERTIFICATE) + JsonTlsLogCertificate(js, ssl_state); + + /* tls.chain */ + if (tls_ctx->fields & LOG_TLS_FIELD_CHAIN) + JsonTlsLogChain(js, ssl_state); } void JsonTlsLogJSONExtended(json_t *tjs, SSLState * state) @@ -447,6 +504,14 @@ OutputCtx *OutputTlsLogInitSub(ConfNode *conf, OutputCtx *parent_ctx) tls_ctx->file_ctx = ojc->file_ctx; + if ((tls_ctx->fields & LOG_TLS_FIELD_CERTIFICATE) && + (tls_ctx->fields & LOG_TLS_FIELD_CHAIN)) { + SCLogWarning(SC_WARN_DUPLICATE_OUTPUT, + "Both 'certificate' and 'chain' contains the top " + "certificate, so only one of them should be enabled " + "at a time"); + } + output_ctx->data = tls_ctx; output_ctx->DeInit = OutputTlsLogDeinitSub; diff --git a/src/util-error.c b/src/util-error.c index 4503986fb5..c9ad9854eb 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -333,6 +333,7 @@ const char * SCErrorToString(SCError err) CASE_CODE (SC_ERR_DNP3_CONFIG); CASE_CODE (SC_ERR_DIR_OPEN); CASE_CODE(SC_WARN_REMOVE_FILE); + CASE_CODE (SC_WARN_DUPLICATE_OUTPUT); CASE_CODE (SC_ERR_NO_MAGIC_SUPPORT); CASE_CODE (SC_ERR_REDIS); CASE_CODE (SC_ERR_VAR_LIMIT); diff --git a/src/util-error.h b/src/util-error.h index 59778c5606..718ba543f4 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -326,6 +326,7 @@ typedef enum { SC_ERR_NO_MAGIC_SUPPORT, SC_ERR_REDIS, SC_ERR_VAR_LIMIT, + SC_WARN_DUPLICATE_OUTPUT, } SCError; const char *SCErrorToString(SCError); diff --git a/suricata.yaml.in b/suricata.yaml.in index 9db8096eac..0222b187e2 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -208,7 +208,7 @@ outputs: extended: yes # enable this for extended logging information # custom allows to control which tls fields that are included # in eve-log - #custom: [subject, issuer, fingerprint, sni, version, not_before, not_after] + #custom: [subject, issuer, fingerprint, sni, version, not_before, not_after, certificate, chain] - files: force-magic: no # force logging magic on all logged files # force logging of checksums, available hash functions are md5,