diff --git a/rust/src/dns/detect.rs b/rust/src/dns/detect.rs index 0d2f0feb7f..9206db3036 100644 --- a/rust/src/dns/detect.rs +++ b/rust/src/dns/detect.rs @@ -29,14 +29,17 @@ use crate::detect::{ SIGMATCH_INFO_MULTI_UINT, SIGMATCH_INFO_UINT16, SIGMATCH_INFO_UINT8, }; use crate::direction::Direction; +use crate::http2::http2::{HTTP2TxProgress, HTTP2TxType}; use std::ffi::CStr; use std::os::raw::{c_int, c_void}; use suricata_sys::sys::{ - DetectEngineCtx, DetectEngineThreadCtx, Flow, SCDetectBufferSetActiveList, - SCDetectHelperBufferProgressRegister, SCDetectHelperKeywordAliasRegister, - SCDetectHelperKeywordRegister, SCDetectHelperMultiBufferProgressMpmRegister, - SCDetectSignatureSetAppProto, SCSigMatchAppendSMToList, SCSigTableAppLiteElmt, SigMatchCtx, - Signature, SIGMATCH_SUPPORT_FIREWALL, + AppProtoEnum, DetectEngineCtx, DetectEngineThreadCtx, Flow, SCDetectBufferSetActiveList, + SCDetectHelperBufferProgressRegister, SCDetectHelperBufferProgressRegisterSubState, + SCDetectHelperKeywordAliasRegister, SCDetectHelperKeywordRegister, + SCDetectHelperMultiBufferProgressMpmRegister, + SCDetectHelperMultiBufferProgressMpmRegisterSubState, SCDetectSignatureSetAppProto, + SCSigMatchAppendSMToList, SCSigTableAppLiteElmt, SigMatchCtx, Signature, + SIGMATCH_SUPPORT_FIREWALL, }; /// Perform the DNS opcode match. @@ -374,6 +377,18 @@ pub unsafe extern "C" fn SCDetectDNSRegister() { Some(dns_tx_get_answer_name), 1, // response complete ); + _ = SCDetectHelperMultiBufferProgressMpmRegisterSubState( + b"dns.answer.name\0".as_ptr() as *const libc::c_char, + b"dns answer name\0".as_ptr() as *const libc::c_char, + AppProtoEnum::ALPROTO_DOH2 as u16, + STREAM_TOSERVER | STREAM_TOCLIENT, + /* Register also in the TO_SERVER direction, even though this is not + normal, it could be provided as part of a request. */ + Some(dns_tx_get_answer_name), + HTTP2TxType::HTTP2TxTypeStream as u8, + HTTP2TxProgress::HTTP2ProgClosed as u8, + ); + let kw = SCSigTableAppLiteElmt { name: b"dns.opcode\0".as_ptr() as *const libc::c_char, desc: b"Match the DNS header opcode flag.\0".as_ptr() as *const libc::c_char, @@ -390,6 +405,14 @@ pub unsafe extern "C" fn SCDetectDNSRegister() { STREAM_TOSERVER | STREAM_TOCLIENT, 1, ); + _ = SCDetectHelperBufferProgressRegisterSubState( + b"dns.opcode\0".as_ptr() as *const libc::c_char, + AppProtoEnum::ALPROTO_DOH2 as u16, + STREAM_TOSERVER | STREAM_TOCLIENT, + HTTP2TxType::HTTP2TxTypeStream as u8, + HTTP2TxProgress::HTTP2ProgClosed as u8, + ); + let kw = SigTableElmtStickyBuffer { name: String::from("dns.query.name"), desc: String::from("DNS query name sticky buffer"), @@ -407,6 +430,18 @@ pub unsafe extern "C" fn SCDetectDNSRegister() { Some(dns_tx_get_query_name), 1, // request or response complete ); + _ = SCDetectHelperMultiBufferProgressMpmRegisterSubState( + b"dns.query.name\0".as_ptr() as *const libc::c_char, + b"dns query name\0".as_ptr() as *const libc::c_char, + AppProtoEnum::ALPROTO_DOH2 as u16, + STREAM_TOSERVER | STREAM_TOCLIENT, + /* Register in both directions as the query is usually echoed back + in the response. */ + Some(dns_tx_get_query_name), + HTTP2TxType::HTTP2TxTypeStream as u8, + HTTP2TxProgress::HTTP2ProgClosed as u8, + ); + let kw = SCSigTableAppLiteElmt { name: b"dns.rcode\0".as_ptr() as *const libc::c_char, desc: b"Match the DNS header rcode flag.\0".as_ptr() as *const libc::c_char, @@ -423,6 +458,14 @@ pub unsafe extern "C" fn SCDetectDNSRegister() { STREAM_TOSERVER | STREAM_TOCLIENT, 1, ); + _ = SCDetectHelperBufferProgressRegisterSubState( + b"dns.rcode\0".as_ptr() as *const libc::c_char, + AppProtoEnum::ALPROTO_DOH2 as u16, + STREAM_TOSERVER | STREAM_TOCLIENT, + HTTP2TxType::HTTP2TxTypeStream as u8, + HTTP2TxProgress::HTTP2ProgClosed as u8, + ); + let kw = SCSigTableAppLiteElmt { name: b"dns.rrtype\0".as_ptr() as *const libc::c_char, desc: b"Match the DNS rrtype in message body.\0".as_ptr() as *const libc::c_char, @@ -439,6 +482,14 @@ pub unsafe extern "C" fn SCDetectDNSRegister() { STREAM_TOSERVER | STREAM_TOCLIENT, 1, ); + _ = SCDetectHelperBufferProgressRegisterSubState( + b"dns.rrtype\0".as_ptr() as *const libc::c_char, + AppProtoEnum::ALPROTO_DOH2 as u16, + STREAM_TOSERVER | STREAM_TOCLIENT, + HTTP2TxType::HTTP2TxTypeStream as u8, + HTTP2TxProgress::HTTP2ProgClosed as u8, + ); + let kw = SigTableElmtStickyBuffer { name: String::from("dns.query"), desc: String::from("sticky buffer to match DNS query-buffer"), @@ -458,6 +509,15 @@ pub unsafe extern "C" fn SCDetectDNSRegister() { Some(dns_tx_get_query), // reuse, will be called only toserver 1, // request complete ); + _ = SCDetectHelperMultiBufferProgressMpmRegisterSubState( + b"dns_query\0".as_ptr() as *const libc::c_char, + b"dns request query\0".as_ptr() as *const libc::c_char, + AppProtoEnum::ALPROTO_DOH2 as u16, + STREAM_TOSERVER, + Some(dns_tx_get_query), + HTTP2TxType::HTTP2TxTypeStream as u8, + HTTP2TxProgress::HTTP2ProgClosed as u8, + ); } #[cfg(test)] diff --git a/src/detect-dns-name.c b/src/detect-dns-name.c index a47ec1cb9b..672461816d 100644 --- a/src/detect-dns-name.c +++ b/src/detect-dns-name.c @@ -173,21 +173,39 @@ static int Register(const char *keyword, const char *desc, const char *doc, return DetectBufferTypeGetByName(keyword); } +/* helper to register the same buffer for DOH2 as we had for DNS, with their + * own alproto, substate and progress. But don't reregister the keyword itself. */ +static void RegisterDoh2(const char *keyword, InspectionMultiBufferGetDataPtr GetBufferFn) +{ + const AppProto alproto = ALPROTO_DOH2; + DetectAppLayerMultiRegisterSubState(keyword, alproto, SIG_FLAG_TOSERVER, HTTP2TxTypeStream, + HTTP2ProgClosed, GetBufferFn, 2); + DetectAppLayerMultiRegisterSubState(keyword, alproto, SIG_FLAG_TOCLIENT, HTTP2TxTypeStream, + HTTP2ProgClosed, GetBufferFn, 2); +} + void DetectDnsNameRegister(void) { query_buffer_id = Register("dns.queries.rrname", "DNS query rrname sticky buffer", "/rules/dns-keywords.html#dns-queries-rrname", SetupQueryBuffer, SCDnsTxGetQueryName, ALPROTO_DNS); + RegisterDoh2("dns.queries.rrname", SCDnsTxGetQueryName); + answer_buffer_id = Register("dns.answers.rrname", "DNS answer rrname sticky buffer", "/rules/dns-keywords.html#dns-answers-rrname", SetupAnswerBuffer, SCDnsTxGetAnswerName, ALPROTO_DNS); + RegisterDoh2("dns.answers.rrname", SCDnsTxGetAnswerName); + additional_buffer_id = Register("dns.additionals.rrname", "DNS additionals rrname sticky buffer", "/rules/dns-keywords.html#dns-additionals-rrname", SetupAdditionalsBuffer, SCDnsTxGetAdditionalName, ALPROTO_DNS); + RegisterDoh2("dns.additionals.rrname", SCDnsTxGetAdditionalName); + authority_buffer_id = Register("dns.authorities.rrname", "DNS authorities rrname sticky buffer", "/rules/dns-keywords.html#dns-authorities-rrname", SetupAuthoritiesBuffer, SCDnsTxGetAuthorityName, ALPROTO_DNS); + RegisterDoh2("dns.authorities.rrname", SCDnsTxGetAuthorityName); mdns_query_buffer_id = Register("mdns.queries.rrname", "mDNS query rrname sticky buffer", "/rules/mdns-keywords.html#mdns-queries-rrname", SetupQueryBufferMdns, diff --git a/src/detect-dns-response.c b/src/detect-dns-response.c index 98e9734044..961a738e20 100644 --- a/src/detect-dns-response.c +++ b/src/detect-dns-response.c @@ -334,9 +334,9 @@ static int DetectDnsResponsePrefilterMpmRegister(DetectEngineCtx *de_ctx, SigGro pectx->mpm_ctx = mpm_ctx; pectx->transforms = &mpm_reg->transforms; - return PrefilterAppendTxEngine(de_ctx, sgh, DetectDnsResponsePrefilterTx, - mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress, pectx, - DetectDnsResponsePrefilterMpmFree, mpm_reg->pname); + return PrefilterAppendTxEngineSubState(de_ctx, sgh, DetectDnsResponsePrefilterTx, + mpm_reg->app_v2.alproto, mpm_reg->app_v2.sub_state, mpm_reg->app_v2.tx_min_progress, + pectx, DetectDnsResponsePrefilterMpmFree, mpm_reg->pname); } static void SCDetectMdnsResponseRrnameRegister(void) @@ -400,6 +400,13 @@ void DetectDnsResponseRegister(void) DetectAppLayerMpmRegister(keyword, SIG_FLAG_TOCLIENT, 2, DetectDnsResponsePrefilterMpmRegister, NULL, ALPROTO_DNS, 1); + /* DOH2: Register in the TO_CLIENT direction. */ + DetectAppLayerInspectEngineRegisterSubState(keyword, ALPROTO_DOH2, SIG_FLAG_TOCLIENT, + HTTP2TxTypeStream, HTTP2ProgClosed, DetectEngineInspectCb, NULL); + DetectAppLayerMpmRegisterSubState(keyword, SIG_FLAG_TOCLIENT, 2, + DetectDnsResponsePrefilterMpmRegister, NULL, ALPROTO_DOH2, HTTP2TxTypeStream, + HTTP2ProgClosed); + DetectBufferTypeSetDescriptionByName(keyword, "dns response rrname"); DetectBufferTypeSupportsMultiInstance(keyword);