tls: parse client certificates

Parse client cerificates and store them in the state similar to how
this is done for server certificates.

Update "progress" handling to not consider the TLS handshake complete
if the server indicated a client cert was needed.
pull/7896/head
Victor Julien 3 years ago
parent 10f5e6cb66
commit e817a8f968

@ -1478,21 +1478,21 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, const uint8_t *input,
break;
case SSLV3_HS_CERTIFICATE:
/* For now, only decode the server certificate */
if (direction == 0) {
SCLogDebug("Incorrect SSL Record type sent in the toserver "
"direction!");
break;
}
rc = SSLv3ParseHandshakeTypeCertificate(
ssl_state, &ssl_state->server_connp, initial_input, input_len);
rc = SSLv3ParseHandshakeTypeCertificate(ssl_state,
direction ? &ssl_state->server_connp : &ssl_state->client_connp, initial_input,
input_len);
if (rc < 0)
return rc;
break;
case SSLV3_HS_HELLO_REQUEST:
break;
case SSLV3_HS_CERTIFICATE_REQUEST:
if (direction) {
ssl_state->current_flags = SSL_AL_FLAG_NEED_CLIENT_CERT;
}
break;
case SSLV3_HS_CERTIFICATE_VERIFY:
case SSLV3_HS_FINISHED:
case SSLV3_HS_CERTIFICATE_URL:
@ -2496,8 +2496,12 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
} /* while (input_len) */
/* mark handshake as done if we have subject and issuer */
if (ssl_state->server_connp.cert0_subject &&
ssl_state->server_connp.cert0_issuerdn) {
if ((ssl_state->flags & SSL_AL_FLAG_NEED_CLIENT_CERT) &&
ssl_state->client_connp.cert0_subject && ssl_state->client_connp.cert0_issuerdn) {
SCLogDebug("SSL_AL_FLAG_HANDSHAKE_DONE");
ssl_state->flags |= SSL_AL_FLAG_HANDSHAKE_DONE;
} else if ((ssl_state->flags & SSL_AL_FLAG_NEED_CLIENT_CERT) == 0 &&
ssl_state->server_connp.cert0_subject && ssl_state->server_connp.cert0_issuerdn) {
SCLogDebug("SSL_AL_FLAG_HANDSHAKE_DONE");
ssl_state->flags |= SSL_AL_FLAG_HANDSHAKE_DONE;
}
@ -2539,6 +2543,7 @@ static void *SSLStateAlloc(void *orig_state, AppProto proto_orig)
memset(ssl_state->client_connp.random, 0, TLS_RANDOM_LEN);
memset(ssl_state->server_connp.random, 0, TLS_RANDOM_LEN);
TAILQ_INIT(&ssl_state->server_connp.certs);
TAILQ_INIT(&ssl_state->client_connp.certs);
return (void *)ssl_state;
}
@ -2603,6 +2608,12 @@ static void SSLStateFree(void *p)
SCFree(item);
}
TAILQ_INIT(&ssl_state->server_connp.certs);
/* Free certificate chain */
while ((item = TAILQ_FIRST(&ssl_state->client_connp.certs))) {
TAILQ_REMOVE(&ssl_state->client_connp.certs, item, next);
SCFree(item);
}
TAILQ_INIT(&ssl_state->client_connp.certs);
SCFree(ssl_state);

@ -135,6 +135,8 @@ enum {
/* flag to indicate that client random was filled */
#define TLS_TC_RANDOM_SET BIT_U32(25)
#define SSL_AL_FLAG_NEED_CLIENT_CERT BIT_U32(26)
/* config flags */
#define SSL_TLS_LOG_PEM (1 << 0)

Loading…
Cancel
Save