diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index ff2f1f1eda..4532401717 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -2861,7 +2861,7 @@ global pkt_profile_file: file &redef; ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply ## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end -## dns_message dns_query_reply dns_rejected dns_request +## dns_message dns_query_reply dns_rejected dns_request dns_dynamic_update type dns_msg: record { id: count; ##< Transaction ID. @@ -2877,12 +2877,12 @@ type dns_msg: record { AD: bool; ##< authentic data CD: bool; ##< checking disabled - num_queries: count; ##< Number of query records. - num_answers: count; ##< Number of answer records. - num_auth: count; ##< Number of authoritative records. + num_queries: count; ##< Number of query records. For dynamic update messages, this is the number of zones. + num_answers: count; ##< Number of answer records. For dynamic update messages, this is the number of prerequisites. + num_auth: count; ##< Number of authoritative records. For dynamic update messages, this is the number of updates. num_addl: count; ##< Number of additional records. - is_netbios: bool; ##< Whether this message came from NetBIOS. + is_netbios: bool; ##< Whether this message came from NetBIOS. }; ## A DNS SOA record. diff --git a/src/analyzer/protocol/dns/DNS.cc b/src/analyzer/protocol/dns/DNS.cc index 5180c6ce70..e09a178023 100644 --- a/src/analyzer/protocol/dns/DNS.cc +++ b/src/analyzer/protocol/dns/DNS.cc @@ -136,6 +136,9 @@ void DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query) { return; } + StringValPtr zname = msg.query_name; + uint32_t zclass = msg.aclass; + if ( ! ParseAnswers(&msg, msg.an_pr_count, detail::DNS_PREREQUISITES, data, len, msg_start) ) { EndMessage(&msg); return; @@ -145,6 +148,12 @@ void DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query) { EndMessage(&msg); return; } + + // Send an event if the first three parts parsed correctly, since they're the + // actual update bits. + if ( dns_dynamic_update ) + analyzer->EnqueueConnEvent(dns_dynamic_update, analyzer->ConnVal(), msg.BuildHdrVal(), zname, + val_mgr->Count(zclass)); } else { if ( ! ParseQuestions(&msg, data, len, msg_start) ) { diff --git a/src/analyzer/protocol/dns/DNS.h b/src/analyzer/protocol/dns/DNS.h index d0921fe6c7..e86d7c6f55 100644 --- a/src/analyzer/protocol/dns/DNS.h +++ b/src/analyzer/protocol/dns/DNS.h @@ -337,7 +337,7 @@ public: StringValPtr query_name; RR_Type atype = TYPE_ALL; - int aclass = 0; ///< normally = 1, inet + uint16_t aclass = 0; ///< normally = 1, inet uint32_t ttl = 0; DNS_AnswerType answer_type = DNS_QUESTION; diff --git a/src/analyzer/protocol/dns/events.bif b/src/analyzer/protocol/dns/events.bif index f9bb501157..c5afb755e6 100644 --- a/src/analyzer/protocol/dns/events.bif +++ b/src/analyzer/protocol/dns/events.bif @@ -836,3 +836,16 @@ event dns_HTTPS%(c: connection, msg: dns_msg, ans: dns_answer, https: dns_svcb_r ## dns_rejected dns_request dns_max_queries dns_session_timeout ## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth event dns_end%(c: connection, msg: dns_msg%); + +## Generated for DNS Dynamic Update messages. See `RFC for Dynamic Updates in the Domain Name System (DNS UPDATE) = 0.63. +[id=47952, opcode=5, rcode=0, QR=F, AA=F, TC=F, RD=F, RA=F, Z=0, AD=F, CD=F, num_queries=1, num_answers=1, num_auth=3, num_addl=1, is_netbios=F], stratolab.org, 1, C_INTERNET +[id=47952, opcode=5, rcode=5, QR=T, AA=F, TC=F, RD=F, RA=F, Z=0, AD=F, CD=F, num_queries=1, num_answers=1, num_auth=3, num_addl=1, is_netbios=F], stratolab.org, 1, C_INTERNET +[id=61191, opcode=5, rcode=0, QR=F, AA=F, TC=F, RD=F, RA=F, Z=0, AD=F, CD=F, num_queries=1, num_answers=1, num_auth=3, num_addl=0, is_netbios=F], stratolab.org, 1, C_INTERNET +[id=61191, opcode=5, rcode=0, QR=T, AA=F, TC=F, RD=F, RA=F, Z=0, AD=F, CD=F, num_queries=1, num_answers=1, num_auth=3, num_addl=0, is_netbios=F], stratolab.org, 1, C_INTERNET diff --git a/testing/btest/Baseline/scripts.base.protocols.dns.dynamic-update/weird.log b/testing/btest/Baseline/scripts.base.protocols.dns.dynamic-update/weird.log deleted file mode 100644 index 77bb64abc0..0000000000 --- a/testing/btest/Baseline/scripts.base.protocols.dns.dynamic-update/weird.log +++ /dev/null @@ -1,12 +0,0 @@ -### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path weird -#open XXXX-XX-XX-XX-XX-XX -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source -#types time string addr port addr port string string bool string string -XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.1.106 62763 192.168.1.108 53 DNS_unknown_opcode 5 F zeek DNS -XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 192.168.1.105 62763 192.168.1.108 53 DNS_unknown_opcode 5 F zeek DNS -#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/scripts/base/protocols/dns/dynamic-update.zeek b/testing/btest/scripts/base/protocols/dns/dynamic-update.zeek index 704ee0bb1a..dfc7de0a09 100644 --- a/testing/btest/scripts/base/protocols/dns/dynamic-update.zeek +++ b/testing/btest/scripts/base/protocols/dns/dynamic-update.zeek @@ -1,6 +1,12 @@ -# @TEST-DOC: Tests that a DNS dynamic update packet doesn't error but reports an unknown opcode weird -# @TEST-EXEC: zeek -b -C -r $TRACES/dns/dynamic-update.pcap %INPUT -# @TEST-EXEC: btest-diff weird.log +# @TEST-DOC: Tests that a DNS dynamic update packet is processed. +# @TEST-EXEC: zeek -b -C -r $TRACES/dns/dynamic-update.pcap %INPUT >out 2>&1 +# @TEST-EXEC: btest-diff out +# @TEST-EXEC: ! test -f weird.log @load base/frameworks/notice/weird @load base/protocols/dns + +event dns_dynamic_update(c: connection, msg: dns_msg, zname: string, zclass: count) + { + print msg, zname, zclass, DNS::classes[zclass]; + }