]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
tls: logging for session resumption 2672/head
authorRay Ruvinskiy <ray.ruvinskiy@arcticwolf.com>
Thu, 24 Nov 2016 17:16:09 +0000 (12:16 -0500)
committerVictor Julien <victor@inliniac.net>
Thu, 20 Apr 2017 07:42:14 +0000 (09:42 +0200)
We assume session resumption has occurred if the Client Hello message
included a session id, we have not seen the server certificate, but
we have seen a Change Cipher Spec message from the server.

Previously, these transactions were not logged at all because the
server cert was never seen.

Ticket: https://redmine.openinfosecfoundation.org/issues/1969

doc/userguide/configuration/suricata-yaml.rst
doc/userguide/output/eve/eve-json-format.rst
src/app-layer-ssl.c
src/app-layer-ssl.h
src/log-tlslog.c
src/output-json-tls.c
suricata.yaml.in

index 7505b9e9dc09b7aff9ff9ad4f9bf6c94640ad094..e45517124b160320ee36c99febf59da2967a2274 100644 (file)
@@ -324,6 +324,9 @@ integration with 3rd party tools like logstash.
             #custom: [a, aaaa, cname, mx, ns, ptr, txt]
         - tls:
             extended: yes     # enable this for extended logging information
+            # output TLS transaction where the session is resumed using a
+            # session id
+            #session-resumption: no
         - files:
             force-magic: no   # force logging magic on all logged files
             # force logging of checksums, available hash functions are md5,
index 7020f705c5e4039501807fc35a58120dcace4fd2..2d2a5632a291cd4caeb0abcde79f0c23a452642c 100644 (file)
@@ -205,6 +205,7 @@ Fields
 
 * "subject": The subject field from the TLS certificate
 * "issuer": The issuer field from the TLS certificate
+* "session_resumed": This field has the value of "true" if the TLS session was resumed via a session id. If this field appears, "subject" and "issuer" do not appear, since a TLS certificate is not seen.
 
 If extended logging is enabled the following fields are also included:
 
@@ -232,6 +233,14 @@ Example of regular TLS logging:
       "issuerdn": "C=US, O=Google Inc, CN=Google Internet Authority G2"
   }
 
+Example of regular TLS logging for resumed sessions:
+
+::
+
+  "tls": {
+      "session_resumed": true
+  }
+
 Example of extended TLS logging:
 
 ::
index f6839adc5ff2a91324641807cda560c6b95593aa..239773981924f182b91c5fcd6989a5d92bf63810 100644 (file)
@@ -265,6 +265,9 @@ static int TLSDecodeHandshakeHello(SSLState *ssl_state, uint8_t *input,
 
     /* skip session id */
     uint8_t session_id_length = *(input++);
+    if (session_id_length != 0) {
+        ssl_state->flags |= SSL_AL_FLAG_SSL_CLIENT_SESSION_ID;
+    }
 
     input += session_id_length;
 
@@ -1202,10 +1205,18 @@ static int SSLv3Decode(uint8_t direction, SSLState *ssl_state,
         case SSLV3_CHANGE_CIPHER_SPEC:
             ssl_state->flags |= SSL_AL_FLAG_CHANGE_CIPHER_SPEC;
 
-            if (direction)
+            if (direction) {
                 ssl_state->flags |= SSL_AL_FLAG_SERVER_CHANGE_CIPHER_SPEC;
-            else
+
+               int server_cert_seen = ssl_state->server_connp.cert0_issuerdn != NULL && \
+                                      ssl_state->server_connp.cert0_subject != NULL;
+               if (!server_cert_seen && (ssl_state->flags & SSL_AL_FLAG_SSL_CLIENT_SESSION_ID) != 0) {
+                   ssl_state->flags |= SSL_AL_FLAG_SESSION_RESUMED;
+               }
+
+            } else {
                 ssl_state->flags |= SSL_AL_FLAG_CLIENT_CHANGE_CIPHER_SPEC;
+            }
 
             break;
 
@@ -4102,6 +4113,143 @@ static int SSLParserTest25(void)
     PASS;
 }
 
+static int SSLParserTest26(void)
+{
+    Flow f;
+    uint8_t client_hello[] = {
+        0x16, 0x03, 0x01, 0x02, 0x0e, 0x01, 0x00, 0x02,
+        0x0a, 0x03, 0x03, 0x58, 0x36, 0x15, 0x03, 0x8e,
+        0x07, 0xf9, 0xad, 0x2a, 0xb7, 0x56, 0xbf, 0xe2,
+        0xa2, 0xf8, 0x21, 0xe0, 0xbb, 0x69, 0xc2, 0xd6,
+        0x76, 0xe6, 0x77, 0xfe, 0x09, 0xff, 0x8e, 0xac,
+        0x80, 0xb5, 0x27, 0x20, 0xb7, 0xbb, 0x90, 0x35,
+        0x7a, 0xdd, 0xd9, 0x67, 0xdf, 0x79, 0xd6, 0x16,
+        0x90, 0xf6, 0xd7, 0x5c, 0xd3, 0x07, 0x19, 0x20,
+        0x01, 0x39, 0x76, 0x25, 0x12, 0x32, 0x71, 0xa1,
+        0x84, 0x8d, 0x2d, 0xea, 0x00, 0x88, 0xc0, 0x30,
+        0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14,
+        0xc0, 0x0a, 0x00, 0xa3, 0x00, 0x9f, 0x00, 0x6b,
+        0x00, 0x6a, 0x00, 0x39, 0x00, 0x38, 0x00, 0x88,
+        0x00, 0x87, 0xc0, 0x32, 0xc0, 0x2e, 0xc0, 0x2a,
+        0xc0, 0x26, 0xc0, 0x0f, 0xc0, 0x05, 0x00, 0x9d,
+        0x00, 0x3d, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x12,
+        0xc0, 0x08, 0x00, 0x16, 0x00, 0x13, 0xc0, 0x0d,
+        0xc0, 0x03, 0x00, 0x0a, 0xc0, 0x2f, 0xc0, 0x2b,
+        0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09,
+        0x00, 0xa2, 0x00, 0x9e, 0x00, 0x67, 0x00, 0x40,
+        0x00, 0x33, 0x00, 0x32, 0x00, 0x9a, 0x00, 0x99,
+        0x00, 0x45, 0x00, 0x44, 0xc0, 0x31, 0xc0, 0x2d,
+        0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e, 0xc0, 0x04,
+        0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x96,
+        0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c,
+        0xc0, 0x02, 0x00, 0x05, 0x00, 0x04, 0x00, 0x15,
+        0x00, 0x12, 0x00, 0x09, 0x00, 0xff, 0x01, 0x00,
+        0x01, 0x39, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12,
+        0x00, 0x00, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x79,
+        0x6f, 0x75, 0x74, 0x75, 0x62, 0x65, 0x2e, 0x63,
+        0x6f, 0x6d, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00,
+        0x01, 0x02, 0x00, 0x0a, 0x00, 0x34, 0x00, 0x32,
+        0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x0b,
+        0x00, 0x0c, 0x00, 0x18, 0x00, 0x09, 0x00, 0x0a,
+        0x00, 0x16, 0x00, 0x17, 0x00, 0x08, 0x00, 0x06,
+        0x00, 0x07, 0x00, 0x14, 0x00, 0x15, 0x00, 0x04,
+        0x00, 0x05, 0x00, 0x12, 0x00, 0x13, 0x00, 0x01,
+        0x00, 0x02, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10,
+        0x00, 0x11, 0x00, 0x23, 0x00, 0xb4, 0x05, 0x6c,
+        0xfa, 0x27, 0x6f, 0x12, 0x2f, 0x2a, 0xe5, 0x56,
+        0xcb, 0x42, 0x62, 0x44, 0xf2, 0xd7, 0xd1, 0x05,
+        0x87, 0xd4, 0x52, 0x02, 0x10, 0x85, 0xa4, 0xa6,
+        0x82, 0x6f, 0x6d, 0x7b, 0xaf, 0x11, 0xbe, 0x21,
+        0x7e, 0x7c, 0x36, 0x03, 0x20, 0x29, 0xd8, 0xf9,
+        0xe5, 0x2b, 0xe2, 0x26, 0xb2, 0x27, 0xc7, 0xb9,
+        0xda, 0x59, 0xd7, 0xdc, 0xfd, 0x74, 0x74, 0x76,
+        0xd0, 0x5e, 0xe4, 0xfe, 0x9d, 0xb7, 0x1b, 0x13,
+        0x81, 0xce, 0x63, 0x75, 0x2b, 0x2f, 0x98, 0x3a,
+        0x84, 0x46, 0xd3, 0x0c, 0xb3, 0x01, 0xdb, 0x62,
+        0x51, 0x97, 0x92, 0x1c, 0xa5, 0x94, 0x60, 0xef,
+        0xa6, 0xd8, 0xb2, 0x2f, 0x02, 0x42, 0x5c, 0xac,
+        0xb4, 0xd9, 0x10, 0x2f, 0x7e, 0x89, 0xab, 0xa5,
+        0xd7, 0x56, 0x6d, 0x03, 0xd2, 0x5f, 0x20, 0x2c,
+        0xb6, 0x99, 0x2b, 0x66, 0xbd, 0xd4, 0xde, 0x53,
+        0x76, 0x5c, 0x78, 0xf0, 0xe9, 0x6d, 0xa5, 0xc3,
+        0x1a, 0x9e, 0x61, 0xb2, 0x45, 0xb0, 0xb3, 0x61,
+        0xee, 0xa1, 0x07, 0xab, 0x2f, 0x84, 0xea, 0x43,
+        0x76, 0x4b, 0x3d, 0xb0, 0xbe, 0xa4, 0xb4, 0x21,
+        0xe1, 0xd3, 0xfd, 0x91, 0xe2, 0xe7, 0xf3, 0x38,
+        0x9c, 0x56, 0x5f, 0xa1, 0xde, 0xa8, 0x2f, 0x0a,
+        0x49, 0x6d, 0x44, 0x8e, 0xb7, 0xef, 0x4a, 0x6f,
+        0x79, 0xb2, 0x00, 0x0d, 0x00, 0x20, 0x00, 0x1e,
+        0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01,
+        0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02,
+        0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03,
+        0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x00, 0x0f,
+        0x00, 0x01, 0x01
+    };
+    uint32_t client_hello_len = sizeof(client_hello);
+
+    uint8_t server_hello_change_cipher_spec[] = {
+        0x16, 0x03, 0x03, 0x00, 0x57, 0x02, 0x00, 0x00,
+        0x53, 0x03, 0x03, 0x58, 0x36, 0x15, 0x03, 0x9f,
+        0x3b, 0xf3, 0x11, 0x96, 0x2b, 0xc3, 0xae, 0x91,
+        0x8c, 0x5f, 0x8b, 0x3f, 0x90, 0xbd, 0xa9, 0x26,
+        0x26, 0xb2, 0xfd, 0x12, 0xc5, 0xc5, 0x7b, 0xe4,
+        0xd1, 0x3e, 0x81, 0x20, 0xb7, 0xbb, 0x90, 0x35,
+        0x7a, 0xdd, 0xd9, 0x67, 0xdf, 0x79, 0xd6, 0x16,
+        0x90, 0xf6, 0xd7, 0x5c, 0xd3, 0x07, 0x19, 0x20,
+        0x01, 0x39, 0x76, 0x25, 0x12, 0x32, 0x71, 0xa1,
+        0x84, 0x8d, 0x2d, 0xea, 0xc0, 0x2b, 0x00, 0x00,
+        0x0b, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0b,
+        0x00, 0x02, 0x01, 0x00, 0x14, 0x03, 0x03, 0x00,
+        0x01, 0x01, 0x16, 0x03, 0x03, 0x00, 0x28, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+        0x66, 0xfe, 0x07, 0x08, 0x33, 0x4d, 0xc2, 0x83,
+        0x8e, 0x05, 0x8b, 0xf8, 0xd1, 0xb1, 0xa7, 0x16,
+        0x4b, 0x42, 0x5c, 0x3a, 0xa4, 0x31, 0x0f, 0xba,
+        0x84, 0x06, 0xcb, 0x9d, 0xc6, 0xc4, 0x66
+    };
+    uint32_t server_hello_change_cipher_spec_len = sizeof(server_hello_change_cipher_spec);
+
+    TcpSession ssn;
+    AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc();
+
+    memset(&f, 0, sizeof(f));
+    memset(&ssn, 0, sizeof(ssn));
+    FLOW_INITIALIZE(&f);
+    f.protoctx = (void *)&ssn;
+    f.proto = IPPROTO_TCP;
+
+    StreamTcpInitConfig(TRUE);
+
+    FLOWLOCK_WRLOCK(&f);
+    int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS,
+                                STREAM_TOSERVER, client_hello,
+                                client_hello_len);
+    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF(r != 0);
+
+    SSLState *ssl_state = f.alstate;
+    FAIL_IF_NULL(ssl_state);
+
+    FAIL_IF((ssl_state->flags & SSL_AL_FLAG_STATE_CLIENT_HELLO) == 0);
+    FAIL_IF((ssl_state->flags & SSL_AL_FLAG_SSL_CLIENT_SESSION_ID) == 0);
+
+    FLOWLOCK_WRLOCK(&f);
+    r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS, STREAM_TOCLIENT,
+                            server_hello_change_cipher_spec,
+                            server_hello_change_cipher_spec_len);
+    FLOWLOCK_UNLOCK(&f);
+    FAIL_IF(r != 0);
+
+    FAIL_IF((ssl_state->flags & SSL_AL_FLAG_SERVER_CHANGE_CIPHER_SPEC) == 0);
+    FAIL_IF((ssl_state->flags & SSL_AL_FLAG_SESSION_RESUMED) == 0);
+
+    AppLayerParserThreadCtxFree(alp_tctx);
+    StreamTcpFreeConfig(TRUE);
+    FLOW_DESTROY(&f);
+
+    PASS;
+}
+
 #endif /* UNITTESTS */
 
 void SSLParserRegisterTests(void)
@@ -4134,6 +4282,7 @@ void SSLParserRegisterTests(void)
     UtRegisterTest("SSLParserTest23", SSLParserTest23);
     UtRegisterTest("SSLParserTest24", SSLParserTest24);
     UtRegisterTest("SSLParserTest25", SSLParserTest25);
+    UtRegisterTest("SSLParserTest26", SSLParserTest26);
 
     UtRegisterTest("SSLParserMultimsgTest01", SSLParserMultimsgTest01);
     UtRegisterTest("SSLParserMultimsgTest02", SSLParserMultimsgTest02);
index f23757836683a8f09e05e5db952c2ec84dcb08fe..1748803afb94106a142d3b7a1c7440a3774ed34f 100644 (file)
@@ -96,6 +96,12 @@ enum {
 /* flag to indicate that handshake is done */
 #define SSL_AL_FLAG_HANDSHAKE_DONE              0x80000
 
+/* A session ID in the Client Hello message, indicating the client
+   wants to resume a session */
+#define SSL_AL_FLAG_SSL_CLIENT_SESSION_ID       0x100000
+/* Session resumed without a full handshake */
+#define SSL_AL_FLAG_SESSION_RESUMED             0x200000
+
 /* config flags */
 #define SSL_TLS_LOG_PEM                         (1 << 0)
 
index 97158b9daf12cf360699164f07b0b8d7052d979a..fb76d705cffdede3480526eb5af592243cbc8246 100644 (file)
 #define OUTPUT_BUFFER_SIZE 65535
 #define CERT_ENC_BUFFER_SIZE 2048
 
-#define LOG_TLS_DEFAULT     0
-#define LOG_TLS_EXTENDED    1
-#define LOG_TLS_CUSTOM      2
+#define LOG_TLS_DEFAULT            0
+#define LOG_TLS_EXTENDED           1
+#define LOG_TLS_CUSTOM             2
+#define LOG_TLS_SESSION_RESUMPTION 4
 
 #define LOG_TLS_CF_VERSION 'v'
 #define LOG_TLS_CF_DATE_NOT_BEFORE 'd'
@@ -308,6 +309,11 @@ static OutputCtx *LogTlsLogInitCtx(ConfNode *conf)
         }
     }
 
+    const char *session_resumption = ConfNodeLookupChildValue(conf, "session-resumption");
+    if (session_resumption == NULL || ConfValIsTrue(session_resumption)) {
+        tlslog_ctx->flags |= LOG_TLS_SESSION_RESUMPTION;
+    }
+
     OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
     if (unlikely(output_ctx == NULL))
         goto tlslog_error;
@@ -446,8 +452,10 @@ static int LogTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p,
         return 0;
     }
 
-    if (ssl_state->server_connp.cert0_issuerdn == NULL ||
-            ssl_state->server_connp.cert0_subject == NULL) {
+    if (((hlog->flags & LOG_TLS_SESSION_RESUMPTION) == 0 ||
+            (ssl_state->flags & SSL_AL_FLAG_SESSION_RESUMED) == 0) &&
+            (ssl_state->server_connp.cert0_issuerdn == NULL ||
+            ssl_state->server_connp.cert0_subject == NULL)) {
         return 0;
     }
 
@@ -467,10 +475,20 @@ static int LogTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p,
         MemBufferReset(aft->buffer);
         CreateTimeString(&p->ts, timebuf, sizeof(timebuf));
         MemBufferWriteString(aft->buffer,
-                "%s %s:%d -> %s:%d  TLS: Subject='%s' Issuerdn='%s'",
-                timebuf, srcip, sp, dstip, dp,
-                ssl_state->server_connp.cert0_subject,
-                ssl_state->server_connp.cert0_issuerdn);
+                             "%s %s:%d -> %s:%d  TLS:",
+                             timebuf, srcip, sp, dstip, dp);
+
+        if (ssl_state->server_connp.cert0_subject != NULL) {
+            MemBufferWriteString(aft->buffer, " Subject='%s'",
+                                 ssl_state->server_connp.cert0_subject);
+        }
+        if (ssl_state->server_connp.cert0_issuerdn != NULL) {
+            MemBufferWriteString(aft->buffer, " Issuerdn='%s'",
+                                 ssl_state->server_connp.cert0_issuerdn);
+        }
+        if (ssl_state->flags & SSL_AL_FLAG_SESSION_RESUMED) {
+            MemBufferWriteString(aft->buffer, " Session='resumed'");
+        }
 
         if (hlog->flags & LOG_TLS_EXTENDED) {
             LogTlsLogExtended(aft, ssl_state);
index 555c666cc4b70d378f3345627b43282ae4e85f9c..fe7ee3684370f1ae69aeba306bb04e9bb005a074 100644 (file)
@@ -60,20 +60,22 @@ SC_ATOMIC_DECLARE(unsigned int, cert_id);
 
 #define SSL_VERSION_LENGTH 13
 
-#define LOG_TLS_DEFAULT     0
-#define LOG_TLS_EXTENDED    (1 << 0)
-#define LOG_TLS_CUSTOM      (1 << 1)
-
-#define LOG_TLS_FIELD_VERSION     (1 << 0)
-#define LOG_TLS_FIELD_SUBJECT     (1 << 1)
-#define LOG_TLS_FIELD_ISSUER      (1 << 2)
-#define LOG_TLS_FIELD_SERIAL      (1 << 3)
-#define LOG_TLS_FIELD_FINGERPRINT (1 << 4)
-#define LOG_TLS_FIELD_NOTBEFORE   (1 << 5)
-#define LOG_TLS_FIELD_NOTAFTER    (1 << 6)
-#define LOG_TLS_FIELD_SNI         (1 << 7)
-#define LOG_TLS_FIELD_CERTIFICATE (1 << 8)
-#define LOG_TLS_FIELD_CHAIN       (1 << 9)
+#define LOG_TLS_DEFAULT                 0
+#define LOG_TLS_EXTENDED                (1 << 0)
+#define LOG_TLS_CUSTOM                  (1 << 1)
+#define LOG_TLS_SESSION_RESUMPTION      (1 << 2)
+
+#define LOG_TLS_FIELD_VERSION           (1 << 0)
+#define LOG_TLS_FIELD_SUBJECT           (1 << 1)
+#define LOG_TLS_FIELD_ISSUER            (1 << 2)
+#define LOG_TLS_FIELD_SERIAL            (1 << 3)
+#define LOG_TLS_FIELD_FINGERPRINT       (1 << 4)
+#define LOG_TLS_FIELD_NOTBEFORE         (1 << 5)
+#define LOG_TLS_FIELD_NOTAFTER          (1 << 6)
+#define LOG_TLS_FIELD_SNI               (1 << 7)
+#define LOG_TLS_FIELD_CERTIFICATE       (1 << 8)
+#define LOG_TLS_FIELD_CHAIN             (1 << 9)
+#define LOG_TLS_FIELD_SESSION_RESUMED   (1 << 10)
 
 typedef struct {
     char *name;
@@ -81,17 +83,18 @@ typedef struct {
 } TlsFields;
 
 TlsFields tls_fields[] = {
-    { "version",     LOG_TLS_FIELD_VERSION },
-    { "subject",     LOG_TLS_FIELD_SUBJECT },
-    { "issuer",      LOG_TLS_FIELD_ISSUER },
-    { "serial",      LOG_TLS_FIELD_SERIAL },
-    { "fingerprint", LOG_TLS_FIELD_FINGERPRINT },
-    { "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 }
+    { "version",         LOG_TLS_FIELD_VERSION },
+    { "subject",         LOG_TLS_FIELD_SUBJECT },
+    { "issuer",          LOG_TLS_FIELD_ISSUER },
+    { "serial",          LOG_TLS_FIELD_SERIAL },
+    { "fingerprint",     LOG_TLS_FIELD_FINGERPRINT },
+    { "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 },
+    { "session_resumed", LOG_TLS_FIELD_SESSION_RESUMED },
+    { NULL,              -1 }
 };
 
 typedef struct OutputTlsCtx_ {
@@ -108,14 +111,25 @@ typedef struct JsonTlsLogThread_ {
 
 static void JsonTlsLogSubject(json_t *js, SSLState *ssl_state)
 {
-    json_object_set_new(js, "subject",
-                        json_string(ssl_state->server_connp.cert0_subject));
+    if (ssl_state->server_connp.cert0_subject) {
+        json_object_set_new(js, "subject",
+                            json_string(ssl_state->server_connp.cert0_subject));
+    }
 }
 
 static void JsonTlsLogIssuer(json_t *js, SSLState *ssl_state)
 {
-    json_object_set_new(js, "issuerdn",
-                        json_string(ssl_state->server_connp.cert0_issuerdn));
+    if (ssl_state->server_connp.cert0_issuerdn) {
+        json_object_set_new(js, "issuerdn",
+                            json_string(ssl_state->server_connp.cert0_issuerdn));
+    }
+}
+
+static void JsonTlsLogSessionResumed(json_t *js, SSLState *ssl_state)
+{
+    if (ssl_state->flags & SSL_AL_FLAG_SESSION_RESUMED) {
+        json_object_set_new(js, "session_resumed", json_boolean(true));
+    }
 }
 
 static void JsonTlsLogFingerprint(json_t *js, SSLState *ssl_state)
@@ -247,6 +261,9 @@ void JsonTlsLogJSONBasic(json_t *js, SSLState *ssl_state)
 
     /* tls issuerdn */
     JsonTlsLogIssuer(js, ssl_state);
+
+    /* tls session resumption */
+    JsonTlsLogSessionResumed(js, ssl_state);
 }
 
 static void JsonTlsLogJSONCustom(OutputTlsCtx *tls_ctx, json_t *js,
@@ -260,6 +277,10 @@ static void JsonTlsLogJSONCustom(OutputTlsCtx *tls_ctx, json_t *js,
     if (tls_ctx->fields & LOG_TLS_FIELD_ISSUER)
         JsonTlsLogIssuer(js, ssl_state);
 
+    /* tls session resumption */
+    if (tls_ctx->fields & LOG_TLS_FIELD_SESSION_RESUMED)
+        JsonTlsLogSessionResumed(js, ssl_state);
+
     /* tls serial */
     if (tls_ctx->fields & LOG_TLS_FIELD_SERIAL)
         JsonTlsLogSerial(js, ssl_state);
@@ -327,8 +348,10 @@ static int JsonTlsLogger(ThreadVars *tv, void *thread_data, const Packet *p,
         return 0;
     }
 
-    if (ssl_state->server_connp.cert0_issuerdn == NULL ||
-            ssl_state->server_connp.cert0_subject == NULL) {
+    if ((ssl_state->server_connp.cert0_issuerdn == NULL ||
+            ssl_state->server_connp.cert0_subject == NULL) &&
+            ((ssl_state->flags & SSL_AL_FLAG_SESSION_RESUMED) == 0 ||
+            (tls_ctx->flags & LOG_TLS_SESSION_RESUMPTION) == 0)) {
         return 0;
     }
 
@@ -456,6 +479,11 @@ static OutputTlsCtx *OutputTlsInitCtx(ConfNode *conf)
         }
     }
 
+    const char *session_resumption = ConfNodeLookupChildValue(conf, "session-resumption");
+    if (session_resumption == NULL || ConfValIsTrue(session_resumption)) {
+        tls_ctx->flags |= LOG_TLS_SESSION_RESUMPTION;
+    }
+
     if ((tls_ctx->fields & LOG_TLS_FIELD_CERTIFICATE) &&
             (tls_ctx->fields & LOG_TLS_FIELD_CHAIN)) {
         SCLogWarning(SC_WARN_DUPLICATE_OUTPUT,
index 8e5ae741364b920bab16eb9290550b9cdef58158..7e94640e0203b646208b34f7865254ed59878cd2 100644 (file)
@@ -207,9 +207,12 @@ outputs:
             #custom: [a, aaaa, cname, mx, ns, ptr, txt]
         - tls:
             extended: yes     # enable this for extended logging information
+            # output TLS transaction where the session is resumed using a
+            # session id
+            #session-resumption: no
             # custom allows to control which tls fields that are included
             # in eve-log
-            #custom: [subject, issuer, serial, fingerprint, sni, version, not_before, not_after, certificate, chain]
+            #custom: [subject, issuer, session_resumed, serial, 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,
@@ -306,6 +309,9 @@ outputs:
       #custom: yes       # enabled the custom logging format (defined by customformat)
       #customformat: "%{%D-%H:%M:%S}t.%z %a:%p -> %A:%P %v %n %d %D"
       #filetype: regular # 'regular', 'unix_stream' or 'unix_dgram'
+      # output TLS transaction where the session is resumed using a
+      # session id
+      #session-resumption: no
 
   # output module to store certificates chain to disk
   - tls-store: