tls: make the client states active phases

The client states were completion milestones: client_hello_done
landed only when the hello record was fully parsed, so during the
in-hello window (possibly multiple packets) the flow sat in
client_in_progress and no firewall state named the phase being
processed.

The states now denote the record phase being processed:
client_hello is entered when the hello message is fully parsed
(it may span several records) and client_cert when the
certificate message is fully parsed, so the phase data (SNI,
certificates) is available when its state is entered; a message
that fails to parse does not advance the track. The milestone
writes are removed and the name table, TOSERVER keyword
registrations (values unchanged) and the firewall user guide
follow the new names.

Ticket: #9047.
pull/16368/head
Victor Julien 1 month ago
parent d286197519
commit 46a75766d2

@ -46,20 +46,20 @@
static SCEnumCharMap tls_state_client_table[] = {
{
"client_in_progress",
TLS_STATE_CLIENT_IN_PROGRESS,
"client_started",
TLS_STATE_CLIENT_STARTED,
},
{
"client_hello_done",
TLS_STATE_CLIENT_HELLO_DONE,
"client_hello",
TLS_STATE_CLIENT_HELLO,
},
{
"client_cert_done",
TLS_STATE_CLIENT_CERT_DONE,
"client_cert",
TLS_STATE_CLIENT_CERT,
},
{
"client_handshake_done",
TLS_STATE_CLIENT_HANDSHAKE_DONE,
"client_data",
TLS_STATE_CLIENT_DATA,
},
{
"client_finished",
@ -1544,9 +1544,7 @@ 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 {
if (ssl_state->curr_connp != &ssl_state->client_connp) {
UpdateServerState(ssl_state, TLS_STATE_SERVER_HELLO);
}
end:
@ -1575,9 +1573,7 @@ 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 {
if (connp != &ssl_state->client_connp) {
UpdateServerState(ssl_state, TLS_STATE_SERVER_CERT_DONE);
}
return input_len;
@ -1694,6 +1690,24 @@ static int SSLv3ParseHandshakeType(SSLState *ssl_state, const uint8_t *input,
return input_len;
}
/**
* \brief advance the phase state once a handshake message is fully parsed
*
* A handshake message may span several records: the started states stay
* in place until the final fragment completes the message, so the phase
* data (SNI, certificates) is available when its state is entered.
*/
static void SSLv3HandshakePhaseAdvance(SSLState *ssl_state)
{
if (ssl_state->curr_connp == &ssl_state->client_connp) {
if (ssl_state->curr_connp->handshake_type == SSLV3_HS_CLIENT_HELLO) {
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HELLO);
} else if (ssl_state->curr_connp->handshake_type == SSLV3_HS_CERTIFICATE) {
UpdateClientState(ssl_state, TLS_STATE_CLIENT_CERT);
}
}
}
static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, const uint8_t *input,
uint32_t input_len, uint8_t direction)
{
@ -1761,6 +1775,8 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, const uint8_t *input
}
SCLogDebug("retval %d", retval);
SSLv3HandshakePhaseAdvance(ssl_state);
/* data processed, reset buffer */
SCFree(ssl_state->curr_connp->hs_buffer);
ssl_state->curr_connp->hs_buffer = NULL;
@ -1856,6 +1872,7 @@ static int SSLv3ParseHandshakeProtocol(SSLState *ssl_state, const uint8_t *input
return (retval);
}
SCLogDebug("retval %d input_len %u", retval, input_len);
SSLv3HandshakePhaseAdvance(ssl_state);
input += retval;
input_len -= retval;
@ -2281,7 +2298,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);
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HELLO);
const uint16_t version = (uint16_t)(input[0] << 8) | input[1];
SCLogDebug("SSLv2: version %04x", version);
@ -2542,7 +2559,7 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
ssl_state->flags |= SSL_AL_FLAG_CLIENT_CHANGE_CIPHER_SPEC;
// TODO TLS 1.3
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HANDSHAKE_DONE);
UpdateClientState(ssl_state, TLS_STATE_CLIENT_DATA);
}
break;
@ -2569,7 +2586,7 @@ static struct SSLDecoderResult SSLv3Decode(uint8_t direction, SSLState *ssl_stat
/* if we see (encrypted) application data, then this means the
handshake must be done */
if (ssl_state->curr_connp == &ssl_state->client_connp) {
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HANDSHAKE_DONE);
UpdateClientState(ssl_state, TLS_STATE_CLIENT_DATA);
} else {
UpdateServerState(ssl_state, TLS_STATE_SERVER_HANDSHAKE_DONE);
}
@ -2808,12 +2825,12 @@ static AppLayerResult SSLDecode(Flow *f, uint8_t direction, void *alstate,
if ((ssl_state->flags & SSL_AL_FLAG_NEED_CLIENT_CERT) &&
ssl_state->client_connp.cert0_subject && ssl_state->client_connp.cert0_issuerdn) {
/* update both sides to keep existing behavior */
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HANDSHAKE_DONE);
UpdateClientState(ssl_state, TLS_STATE_CLIENT_DATA);
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) {
/* update both sides to keep existing behavior */
UpdateClientState(ssl_state, TLS_STATE_CLIENT_HANDSHAKE_DONE);
UpdateClientState(ssl_state, TLS_STATE_CLIENT_DATA);
UpdateServerState(ssl_state, TLS_STATE_SERVER_HANDSHAKE_DONE);
}

@ -77,10 +77,10 @@ enum {
};
enum TlsStateClient {
TLS_STATE_CLIENT_IN_PROGRESS = 0,
TLS_STATE_CLIENT_HELLO_DONE,
TLS_STATE_CLIENT_CERT_DONE,
TLS_STATE_CLIENT_HANDSHAKE_DONE,
TLS_STATE_CLIENT_STARTED = 0,
TLS_STATE_CLIENT_HELLO,
TLS_STATE_CLIENT_CERT,
TLS_STATE_CLIENT_DATA,
TLS_STATE_CLIENT_FINISHED,
};

@ -83,10 +83,10 @@ void DetectJa4HashRegister(void)
#ifdef HAVE_JA4
DetectAppLayerInspectEngineRegister("ja4.hash", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_HELLO_DONE, DetectEngineInspectBufferGeneric, GetData);
TLS_STATE_CLIENT_HELLO, DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("ja4.hash", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO_DONE);
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO);
DetectAppLayerMpmRegister("ja4.hash", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
Ja4DetectGetHash, ALPROTO_QUIC, 1);

@ -95,7 +95,7 @@ void DetectLuaRegister(void)
g_lua_ja3_list_id = DetectBufferTypeRegister("ja3.lua");
DetectAppLayerInspectEngineRegister("ja3.lua", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_HELLO_DONE, DetectEngineInspectGenericList, NULL);
TLS_STATE_CLIENT_HELLO, DetectEngineInspectGenericList, NULL);
DetectAppLayerInspectEngineRegister(
"ja3.lua", ALPROTO_QUIC, SIG_FLAG_TOSERVER, 1, DetectEngineInspectGenericList, NULL);

@ -92,8 +92,8 @@ void DetectTlsAlpnRegister(void)
sigmatch_table[DETECT_TLS_ALPN].flags |=
SIGMATCH_INFO_STICKY_BUFFER | SIGMATCH_INFO_MULTI_BUFFER;
DetectAppLayerMultiRegister("tls.alpn", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_HELLO_DONE, TlsAlpnGetData, 2);
DetectAppLayerMultiRegister(
"tls.alpn", ALPROTO_TLS, SIG_FLAG_TOSERVER, TLS_STATE_CLIENT_HELLO, TlsAlpnGetData, 2);
DetectAppLayerMultiRegister(
"tls.alpn", ALPROTO_TLS, SIG_FLAG_TOCLIENT, TLS_STATE_SERVER_HELLO, TlsAlpnGetData, 2);

@ -89,10 +89,10 @@ void DetectTlsFingerprintRegister(void)
PrefilterGenericMpmRegister, GetData, ALPROTO_TLS, TLS_STATE_SERVER_CERT_DONE);
DetectAppLayerInspectEngineRegister("tls.cert_fingerprint", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_CERT_DONE, DetectEngineInspectBufferGeneric, GetData);
TLS_STATE_CLIENT_CERT, DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("tls.cert_fingerprint", SIG_FLAG_TOSERVER, 2,
PrefilterGenericMpmRegister, GetData, ALPROTO_TLS, TLS_STATE_CLIENT_CERT_DONE);
PrefilterGenericMpmRegister, GetData, ALPROTO_TLS, TLS_STATE_CLIENT_CERT);
DetectBufferTypeSetDescriptionByName("tls.cert_fingerprint",
"TLS certificate fingerprint");

@ -81,10 +81,10 @@ void DetectTlsIssuerRegister(void)
sigmatch_table[DETECT_TLS_CERT_ISSUER].flags |= SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerInspectEngineRegister("tls.cert_issuer", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_CERT_DONE, DetectEngineInspectBufferGeneric, GetData);
TLS_STATE_CLIENT_CERT, DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("tls.cert_issuer", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_CERT_DONE);
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_CERT);
DetectAppLayerInspectEngineRegister("tls.cert_issuer", ALPROTO_TLS, SIG_FLAG_TOCLIENT,
TLS_STATE_SERVER_CERT_DONE, DetectEngineInspectBufferGeneric, GetData);

@ -91,10 +91,10 @@ void DetectTlsSerialRegister(void)
GetData, ALPROTO_TLS, TLS_STATE_SERVER_CERT_DONE);
DetectAppLayerInspectEngineRegister("tls.cert_serial", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_CERT_DONE, DetectEngineInspectBufferGeneric, GetData);
TLS_STATE_CLIENT_CERT, DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("tls.cert_serial", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_CERT_DONE);
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_CERT);
DetectBufferTypeSetDescriptionByName("tls.cert_serial",
"TLS certificate serial number");

@ -81,10 +81,10 @@ void DetectTlsSubjectRegister(void)
sigmatch_table[DETECT_TLS_CERT_SUBJECT].flags |= SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerInspectEngineRegister("tls.cert_subject", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_CERT_DONE, DetectEngineInspectBufferGeneric, GetData);
TLS_STATE_CLIENT_CERT, DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("tls.cert_subject", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_CERT_DONE);
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_CERT);
DetectAppLayerInspectEngineRegister("tls.cert_subject", ALPROTO_TLS, SIG_FLAG_TOCLIENT,
TLS_STATE_SERVER_CERT_DONE, DetectEngineInspectBufferGeneric, GetData);

@ -116,8 +116,8 @@ void DetectTlsCertsRegister(void)
DetectAppLayerMultiRegister("tls.certs", ALPROTO_TLS, SIG_FLAG_TOCLIENT,
TLS_STATE_SERVER_CERT_DONE, TlsCertsGetData, 2);
DetectAppLayerMultiRegister("tls.certs", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_CERT_DONE, TlsCertsGetData, 2);
DetectAppLayerMultiRegister(
"tls.certs", ALPROTO_TLS, SIG_FLAG_TOSERVER, TLS_STATE_CLIENT_CERT, TlsCertsGetData, 2);
DetectBufferTypeSetDescriptionByName("tls.certs", "TLS certificate");

@ -92,10 +92,10 @@ void DetectTlsJa3HashRegister(void)
#ifdef HAVE_JA3
DetectAppLayerInspectEngineRegister("ja3.hash", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_HELLO_DONE, DetectEngineInspectBufferGeneric, GetData);
TLS_STATE_CLIENT_HELLO, DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("ja3.hash", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO_DONE);
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO);
DetectAppLayerMpmRegister("ja3.hash", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
Ja3DetectGetHash, ALPROTO_QUIC, 1);

@ -93,10 +93,10 @@ void DetectTlsJa3StringRegister(void)
#ifdef HAVE_JA3
DetectAppLayerInspectEngineRegister("ja3.string", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_HELLO_DONE, DetectEngineInspectBufferGeneric, GetData);
TLS_STATE_CLIENT_HELLO, DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("ja3.string", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO_DONE);
GetData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO);
DetectAppLayerMpmRegister("ja3.string", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
Ja3DetectGetString, ALPROTO_QUIC, 1);

@ -64,9 +64,9 @@ void DetectTlsRandomTimeRegister(void)
/* Register engine for Server random */
DetectAppLayerInspectEngineRegister("tls.random_time", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_HELLO_DONE, DetectEngineInspectBufferGeneric, GetRandomTimeData);
TLS_STATE_CLIENT_HELLO, DetectEngineInspectBufferGeneric, GetRandomTimeData);
DetectAppLayerMpmRegister("tls.random_time", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetRandomTimeData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO_DONE);
GetRandomTimeData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO);
/* Register engine for Client random */
DetectAppLayerInspectEngineRegister("tls.random_time", ALPROTO_TLS, SIG_FLAG_TOCLIENT,
@ -91,9 +91,9 @@ void DetectTlsRandomBytesRegister(void)
/* Register engine for Server random */
DetectAppLayerInspectEngineRegister("tls.random_bytes", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_HELLO_DONE, DetectEngineInspectBufferGeneric, GetRandomBytesData);
TLS_STATE_CLIENT_HELLO, DetectEngineInspectBufferGeneric, GetRandomBytesData);
DetectAppLayerMpmRegister("tls.random_bytes", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
GetRandomBytesData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO_DONE);
GetRandomBytesData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO);
/* Register engine for Client random */
DetectAppLayerInspectEngineRegister("tls.random_bytes", ALPROTO_TLS, SIG_FLAG_TOCLIENT,

@ -75,10 +75,10 @@ void DetectTlsSniRegister(void)
sigmatch_table[DETECT_TLS_SNI].flags |= SIGMATCH_INFO_STICKY_BUFFER;
DetectAppLayerInspectEngineRegister("tls.sni", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_HELLO_DONE, DetectEngineInspectBufferGeneric, GetData);
TLS_STATE_CLIENT_HELLO, DetectEngineInspectBufferGeneric, GetData);
DetectAppLayerMpmRegister("tls.sni", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister, GetData,
ALPROTO_TLS, TLS_STATE_CLIENT_HELLO_DONE);
ALPROTO_TLS, TLS_STATE_CLIENT_HELLO);
DetectBufferTypeSetDescriptionByName("tls.sni",
"TLS Server Name Indication (SNI) extension");

@ -147,7 +147,7 @@ void DetectTlsRegister (void)
TLS_STATE_SERVER_CERT_DONE, DetectEngineInspectGenericList, NULL);
DetectAppLayerInspectEngineRegister("tls_cert", ALPROTO_TLS, SIG_FLAG_TOSERVER,
TLS_STATE_CLIENT_CERT_DONE, DetectEngineInspectGenericList, NULL);
TLS_STATE_CLIENT_CERT, DetectEngineInspectGenericList, NULL);
}
/**

@ -734,5 +734,5 @@ void JsonTlsLogRegister (void)
/* register as child of eve-log */
OutputRegisterTxSubModuleWithProgress(LOGGER_JSON_TX, "eve-log", "JsonTlsLog", "eve-log.tls",
OutputTlsLogInitSub, ALPROTO_TLS, JsonTlsLogger, TLS_STATE_SERVER_HANDSHAKE_DONE,
TLS_STATE_CLIENT_HANDSHAKE_DONE, JsonTlsLogThreadInit, JsonTlsLogThreadDeinit);
TLS_STATE_CLIENT_DATA, JsonTlsLogThreadInit, JsonTlsLogThreadDeinit);
}

@ -794,7 +794,7 @@ static OutputInitResult OutputLuaLogInit(SCConfNode *conf)
om->TxLogFunc = LuaTxLogger;
om->alproto = ALPROTO_TLS;
om->tc_log_progress = TLS_STATE_SERVER_HANDSHAKE_DONE;
om->ts_log_progress = TLS_STATE_CLIENT_HANDSHAKE_DONE;
om->ts_log_progress = TLS_STATE_CLIENT_DATA;
SCAppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_TLS);
} else if (opts.alproto == ALPROTO_DNS) {
om->TxLogFunc = LuaTxLogger;

Loading…
Cancel
Save