diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index f421dccacea2..f9b725053636 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -522,6 +522,7 @@ void SigTableSetup(void) DetectTlsSerialRegister(); DetectTlsFingerprintRegister(); DetectTlsCertsRegister(); + DetectTlsCertChainLenRegister(); DetectTlsRandomRegister(); DetectTlsJa3HashRegister(); diff --git a/src/detect-engine-register.h b/src/detect-engine-register.h index f5b72f15b811..9ad74d721aaa 100644 --- a/src/detect-engine-register.h +++ b/src/detect-engine-register.h @@ -116,6 +116,7 @@ enum DetectKeywordId { DETECT_AL_TLS_VALID, DETECT_AL_TLS_FINGERPRINT, DETECT_AL_TLS_STORE, + DETECT_AL_TLS_CHAIN_LEN, DETECT_AL_HTTP_COOKIE, DETECT_HTTP_COOKIE, diff --git a/src/detect-tls-certs.c b/src/detect-tls-certs.c index d238fc4d54bf..28b0f82ccab9 100644 --- a/src/detect-tls-certs.c +++ b/src/detect-tls-certs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Open Information Security Foundation +/* Copyright (C) 2019-2022 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -36,6 +36,7 @@ #include "detect-content.h" #include "detect-pcre.h" #include "detect-tls-certs.h" +#include "detect-engine-uint.h" #include "flow.h" #include "flow-util.h" @@ -247,6 +248,113 @@ static int PrefilterMpmTlsCertsRegister(DetectEngineCtx *de_ctx, pectx, PrefilterMpmTlsCertsFree, mpm_reg->name); } +static int g_tls_cert_buffer_id = 0; +#define BUFFER_NAME "tls_validity" +#define KEYWORD_ID DETECT_AL_TLS_CHAIN_LEN +#define KEYWORD_NAME "tls.cert_chain_len" +#define KEYWORD_DESC "match TLS certificate chain length" +#define KEYWORD_URL "/rules/tls-keywords.html#tls-cert-chain-len" + +/** + * \internal + * \brief Function to match cert chain length in TLS + * + * \param t Pointer to thread vars. + * \param det_ctx Pointer to the pattern matcher thread. + * \param f Pointer to the current flow. + * \param flags Flags. + * \param state App layer state. + * \param s Pointer to the Signature. + * \param m Pointer to the sigmatch that we will cast into + * DetectU64Data. + * + * \retval 0 no match. + * \retval 1 match. + */ +static int DetectTLSCertChainLenMatch(DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, + void *state, void *txv, const Signature *s, const SigMatchCtx *ctx) +{ + SCEnter(); + + SSLState *ssl_state = state; + if (flags & STREAM_TOCLIENT) { + SSLStateConnp *connp = &ssl_state->server_connp; + uint32_t cnt = 0; + SSLCertsChain *cert; + TAILQ_FOREACH (cert, &connp->certs, next) { + cnt++; + } + SCLogDebug("%u certs in chain", cnt); + + const DetectU32Data *dd = (const DetectU32Data *)ctx; + if (DetectU32Match(cnt, dd)) { + SCReturnInt(1); + } + } + SCReturnInt(0); +} + +/** + * \internal + * \brief Function to free memory associated with DetectU64Data. + * + * \param de_ptr Pointer to DetectU64Data. + */ +static void DetectTLSCertChainLenFree(DetectEngineCtx *de_ctx, void *ptr) +{ + rs_detect_u32_free(ptr); +} + +/** + * \brief Function to add the parsed tls cert chain len field into the current signature. + * + * \param de_ctx Pointer to the Detection Engine Context. + * \param s Pointer to the Current Signature. + * \param rawstr Pointer to the user provided flags options. + * \param type Defines if this is notBefore or notAfter. + * + * \retval 0 on Success. + * \retval -1 on Failure. + */ +static int DetectTLSCertChainLenSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr) +{ + if (DetectSignatureSetAppProto(s, ALPROTO_TLS) != 0) + return -1; + + DetectU32Data *dd = DetectU32Parse(rawstr); + if (dd == NULL) { + SCLogError(SC_ERR_INVALID_ARGUMENT, "Parsing \'%s\' failed for %s", rawstr, + sigmatch_table[KEYWORD_ID].name); + return -1; + } + + SigMatch *sm = SigMatchAlloc(); + if (sm == NULL) { + rs_detect_u32_free(dd); + return -1; + } + sm->type = KEYWORD_ID; + sm->ctx = (void *)dd; + + SigMatchAppendSMToList(s, sm, g_tls_cert_buffer_id); + return 0; +} + +void DetectTlsCertChainLenRegister(void) +{ + sigmatch_table[KEYWORD_ID].name = KEYWORD_NAME; + sigmatch_table[KEYWORD_ID].desc = KEYWORD_DESC; + sigmatch_table[KEYWORD_ID].url = KEYWORD_URL; + sigmatch_table[KEYWORD_ID].AppLayerTxMatch = DetectTLSCertChainLenMatch; + sigmatch_table[KEYWORD_ID].Setup = DetectTLSCertChainLenSetup; + sigmatch_table[KEYWORD_ID].Free = DetectTLSCertChainLenFree; + + DetectAppLayerInspectEngineRegister2(BUFFER_NAME, ALPROTO_TLS, SIG_FLAG_TOCLIENT, + TLS_STATE_CERT_READY, DetectEngineInspectGenericList, NULL); + + g_tls_cert_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME); +} + #ifdef UNITTESTS #include "tests/detect-tls-certs.c" #endif diff --git a/src/detect-tls-certs.h b/src/detect-tls-certs.h index 2ef88065f043..1dde64ddd727 100644 --- a/src/detect-tls-certs.h +++ b/src/detect-tls-certs.h @@ -25,5 +25,6 @@ #define __DETECT_TLS_CERTS_H__ void DetectTlsCertsRegister(void); +void DetectTlsCertChainLenRegister(void); #endif /* __DETECT_TLS_CERTS_H__ */