/* 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;
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;
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)
UtRegisterTest("SSLParserTest23", SSLParserTest23);
UtRegisterTest("SSLParserTest24", SSLParserTest24);
UtRegisterTest("SSLParserTest25", SSLParserTest25);
+ UtRegisterTest("SSLParserTest26", SSLParserTest26);
UtRegisterTest("SSLParserMultimsgTest01", SSLParserMultimsgTest01);
UtRegisterTest("SSLParserMultimsgTest02", SSLParserMultimsgTest02);
#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;
} 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_ {
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)
/* tls issuerdn */
JsonTlsLogIssuer(js, ssl_state);
+
+ /* tls session resumption */
+ JsonTlsLogSessionResumed(js, ssl_state);
}
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);
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;
}
}
}
+ 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,