|
|
|
|
@ -292,30 +292,36 @@ static uint64_t SSLGetTxCnt(void *state)
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int SSLGetAlstateProgress(void *tx, uint8_t direction)
|
|
|
|
|
static void UpdateClientState(SSLState *ssl_state, enum TlsStateClient s)
|
|
|
|
|
{
|
|
|
|
|
SSLState *ssl_state = (SSLState *)tx;
|
|
|
|
|
|
|
|
|
|
/* we don't care about direction, only that app-layer parser is done
|
|
|
|
|
and have sent an EOF */
|
|
|
|
|
if (ssl_state->flags & SSL_AL_FLAG_STATE_FINISHED) {
|
|
|
|
|
return TLS_STATE_FINISHED;
|
|
|
|
|
}
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
enum TlsStateClient old = ssl_state->client_state;
|
|
|
|
|
#endif
|
|
|
|
|
ssl_state->client_state = s;
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
SCLogDebug("toserver: state updated to %u from %u", s, old);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* we want the logger to log when the handshake is done, even if the
|
|
|
|
|
state is not finished */
|
|
|
|
|
if (ssl_state->flags & SSL_AL_FLAG_HANDSHAKE_DONE) {
|
|
|
|
|
return TLS_HANDSHAKE_DONE;
|
|
|
|
|
}
|
|
|
|
|
static void UpdateServerState(SSLState *ssl_state, enum TlsStateServer s)
|
|
|
|
|
{
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
enum TlsStateServer old = ssl_state->server_state;
|
|
|
|
|
#endif
|
|
|
|
|
ssl_state->server_state = s;
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
SCLogDebug("toclient: state updated to %u from %u", s, old);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (direction == STREAM_TOSERVER &&
|
|
|
|
|
(ssl_state->server_connp.cert0_subject != NULL ||
|
|
|
|
|
ssl_state->server_connp.cert0_issuerdn != NULL))
|
|
|
|
|
{
|
|
|
|
|
return TLS_STATE_CERT_READY;
|
|
|
|
|
static int SSLGetAlstateProgress(void *tx, uint8_t direction)
|
|
|
|
|
{
|
|
|
|
|
SSLState *ssl_state = (SSLState *)tx;
|
|
|
|
|
if (direction & STREAM_TOCLIENT) {
|
|
|
|
|
return ssl_state->server_state;
|
|
|
|
|
} else {
|
|
|
|
|
return ssl_state->client_state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TLS_STATE_IN_PROGRESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static AppLayerTxData *SSLGetTxData(void *vtx)
|
|
|
|
|
@ -1610,6 +1616,11 @@ static int TLSDecodeHandshakeHello(SSLState *ssl_state,
|
|
|
|
|
ssl_state->curr_connp->ja3_hash = Ja3GenerateHash(ssl_state->curr_connp->ja3_str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ssl_state->curr_connp == &ssl_state->client_connp) {
|
|
|
|
|
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HELLO_DONE);
|
|
|
|
|
} else {
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_HELLO);
|
|
|
|
|
}
|
|
|
|
|
end:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@ -1636,6 +1647,11 @@ static inline int SSLv3ParseHandshakeTypeCertificate(SSLState *ssl_state, SSLSta
|
|
|
|
|
SSLParserHSReset(connp);
|
|
|
|
|
/* fall through to still consume the cert bytes */
|
|
|
|
|
}
|
|
|
|
|
if (connp == &ssl_state->client_connp) {
|
|
|
|
|
UpdateClientState(ssl_state, TLS_STATE_CLIENT_CERT_DONE);
|
|
|
|
|
} else {
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_CERT_DONE);
|
|
|
|
|
}
|
|
|
|
|
return input_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1704,7 +1720,6 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, const uint8_t *input,
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SSLV3_HS_CERTIFICATE:
|
|
|
|
|
|
|
|
|
|
rc = SSLv3ParseHandshakeTypeCertificate(ssl_state,
|
|
|
|
|
direction ? &ssl_state->server_connp : &ssl_state->client_connp, initial_input,
|
|
|
|
|
input_len);
|
|
|
|
|
@ -1728,6 +1743,9 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, const uint8_t *input,
|
|
|
|
|
SCLogDebug("new session ticket");
|
|
|
|
|
break;
|
|
|
|
|
case SSLV3_HS_SERVER_HELLO_DONE:
|
|
|
|
|
if (direction) {
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_HELLO_DONE);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
|
|
|
|
|
@ -1940,7 +1958,8 @@ static int SSLv3ParseAlertProtocol(
|
|
|
|
|
|
|
|
|
|
/* if level Fatal, we consider the tx finished */
|
|
|
|
|
if (level == 2) {
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_STATE_FINISHED;
|
|
|
|
|
UpdateClientState(ssl_state, TLS_STATE_CLIENT_FINISHED);
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_FINISHED);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
@ -2323,6 +2342,7 @@ static struct SSLDecoderResult SSLv2Decode(uint8_t direction, SSLState *ssl_stat
|
|
|
|
|
|
|
|
|
|
ssl_state->current_flags = SSL_AL_FLAG_STATE_CLIENT_HELLO;
|
|
|
|
|
ssl_state->current_flags |= SSL_AL_FLAG_SSL_CLIENT_HS;
|
|
|
|
|
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HELLO_DONE);
|
|
|
|
|
|
|
|
|
|
const uint16_t version = (uint16_t)(input[0] << 8) | input[1];
|
|
|
|
|
SCLogDebug("SSLv2: version %04x", version);
|
|
|
|
|
@ -2352,6 +2372,7 @@ static struct SSLDecoderResult SSLv2Decode(uint8_t direction, SSLState *ssl_stat
|
|
|
|
|
} else {
|
|
|
|
|
ssl_state->current_flags = SSL_AL_FLAG_STATE_CLIENT_KEYX;
|
|
|
|
|
}
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_CERT_DONE);
|
|
|
|
|
|
|
|
|
|
/* fall through */
|
|
|
|
|
case SSLV2_MT_SERVER_VERIFY:
|
|
|
|
|
@ -2404,6 +2425,7 @@ static struct SSLDecoderResult SSLv2Decode(uint8_t direction, SSLState *ssl_stat
|
|
|
|
|
case SSLV2_MT_SERVER_HELLO:
|
|
|
|
|
ssl_state->current_flags = SSL_AL_FLAG_STATE_SERVER_HELLO;
|
|
|
|
|
ssl_state->current_flags |= SSL_AL_FLAG_SSL_SERVER_HS;
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_HELLO);
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@ -2570,6 +2592,9 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_SERVER_CHANGE_CIPHER_SPEC;
|
|
|
|
|
} else {
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_CLIENT_CHANGE_CIPHER_SPEC;
|
|
|
|
|
|
|
|
|
|
// TODO TLS 1.3
|
|
|
|
|
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HANDSHAKE_DONE);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
@ -2595,7 +2620,11 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
|
|
|
|
|
|
|
|
|
|
/* if we see (encrypted) application data, then this means the
|
|
|
|
|
handshake must be done */
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_HANDSHAKE_DONE;
|
|
|
|
|
if (ssl_state->curr_connp == &ssl_state->client_connp) {
|
|
|
|
|
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HANDSHAKE_DONE);
|
|
|
|
|
} else {
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_HANDSHAKE_DONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ssl_config.encrypt_mode != SSL_CNF_ENC_HANDLE_FULL) {
|
|
|
|
|
SCLogDebug("setting APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD");
|
|
|
|
|
@ -2723,7 +2752,10 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
|
|
|
|
|
(direction == 1 &&
|
|
|
|
|
AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)))) {
|
|
|
|
|
/* flag session as finished if APP_LAYER_PARSER_EOF is set */
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_STATE_FINISHED;
|
|
|
|
|
if (direction == 0)
|
|
|
|
|
UpdateClientState(ssl_state, TLS_STATE_CLIENT_FINISHED);
|
|
|
|
|
else
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_FINISHED);
|
|
|
|
|
SCReturnStruct(APP_LAYER_OK);
|
|
|
|
|
} else if (input == NULL || input_len == 0) {
|
|
|
|
|
SCReturnStruct(APP_LAYER_ERROR);
|
|
|
|
|
@ -2831,19 +2863,22 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
|
|
|
|
|
/* mark handshake as done if we have subject and issuer */
|
|
|
|
|
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;
|
|
|
|
|
/* update both sides to keep existing behavior */
|
|
|
|
|
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HANDSHAKE_DONE);
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_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;
|
|
|
|
|
/* update both sides to keep existing behavior */
|
|
|
|
|
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HANDSHAKE_DONE);
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_HANDSHAKE_DONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* flag session as finished if APP_LAYER_PARSER_EOF is set */
|
|
|
|
|
if (AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS) &&
|
|
|
|
|
AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TC)) {
|
|
|
|
|
SCLogDebug("SSL_AL_FLAG_STATE_FINISHED");
|
|
|
|
|
ssl_state->flags |= SSL_AL_FLAG_STATE_FINISHED;
|
|
|
|
|
/* update both sides to keep existing behavior */
|
|
|
|
|
UpdateClientState(ssl_state, TLS_STATE_CLIENT_FINISHED);
|
|
|
|
|
UpdateServerState(ssl_state, TLS_STATE_SERVER_FINISHED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return APP_LAYER_OK;
|
|
|
|
|
@ -3307,7 +3342,7 @@ void RegisterSSLParsers(void)
|
|
|
|
|
AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_TLS, SSLGetAlstateProgress);
|
|
|
|
|
|
|
|
|
|
AppLayerParserRegisterStateProgressCompletionStatus(
|
|
|
|
|
ALPROTO_TLS, TLS_STATE_FINISHED, TLS_STATE_FINISHED);
|
|
|
|
|
ALPROTO_TLS, TLS_STATE_CLIENT_FINISHED, TLS_STATE_SERVER_FINISHED);
|
|
|
|
|
|
|
|
|
|
SCConfNode *enc_handle = SCConfGetNode("app-layer.protocols.tls.encryption-handling");
|
|
|
|
|
if (enc_handle != NULL && enc_handle->val != NULL) {
|
|
|
|
|
|