diff --git a/scripts/base/protocols/dns/consts.bro b/scripts/base/protocols/dns/consts.bro index 13af6c3e81..026588f777 100644 --- a/scripts/base/protocols/dns/consts.bro +++ b/scripts/base/protocols/dns/consts.bro @@ -26,6 +26,7 @@ export { [49] = "DHCID", [99] = "SPF", [100] = "DINFO", [101] = "UID", [102] = "GID", [103] = "UNSPEC", [249] = "TKEY", [250] = "TSIG", [251] = "IXFR", [252] = "AXFR", [253] = "MAILB", [254] = "MAILA", + [257] = "CAA", [32768] = "TA", [32769] = "DLV", [ANY] = "*", } &default = function(n: count): string { return fmt("query-%d", n); }; diff --git a/src/analyzer/protocol/dns/DNS.cc b/src/analyzer/protocol/dns/DNS.cc index b449589e6c..1fc94a80ba 100644 --- a/src/analyzer/protocol/dns/DNS.cc +++ b/src/analyzer/protocol/dns/DNS.cc @@ -282,6 +282,10 @@ int DNS_Interpreter::ParseAnswer(DNS_MsgInfo* msg, status = ParseRR_TXT(msg, data, len, rdlength, msg_start); break; + case TYPE_CAA: + status = ParseRR_CAA(msg, data, len, rdlength, msg_start); + break; + case TYPE_NBS: status = ParseRR_NBS(msg, data, len, rdlength, msg_start); break; @@ -904,6 +908,51 @@ int DNS_Interpreter::ParseRR_TXT(DNS_MsgInfo* msg, return rdlength == 0; } +int DNS_Interpreter::ParseRR_CAA(DNS_MsgInfo* msg, + const u_char*& data, int& len, int rdlength, + const u_char* msg_start) + { + if ( ! dns_CAA_reply || msg->skip_event ) + { + data += rdlength; + len -= rdlength; + return 1; + } + + unsigned int flags = ExtractShort(data, len); + unsigned int tagLen = flags & 0xff; + flags = flags >> 8; + rdlength -= 2; + if ( (int) tagLen >= rdlength ) + { + analyzer->Weird("DNS_CAA_char_str_past_rdlen"); + return 0; + } + BroString* tag = new BroString(data, tagLen, 1); + len -= tagLen; + data += tagLen; + rdlength -= tagLen; + BroString* value = new BroString(data, rdlength, 0); + + len -= value->Len(); + data += value->Len(); + rdlength -= value->Len(); + + val_list* vl = new val_list; + + vl->append(analyzer->BuildConnVal()); + vl->append(msg->BuildHdrVal()); + vl->append(msg->BuildAnswerVal()); + vl->append(new Val(flags, TYPE_COUNT)); + vl->append(new StringVal(tag)); + vl->append(new StringVal(value)); + + analyzer->ConnectionEvent(dns_CAA_reply, vl); + + return rdlength == 0; + } + + void DNS_Interpreter::SendReplyOrRejectEvent(DNS_MsgInfo* msg, EventHandlerPtr event, const u_char*& data, int& len, diff --git a/src/analyzer/protocol/dns/DNS.h b/src/analyzer/protocol/dns/DNS.h index 54b5d291cc..87618cd18e 100644 --- a/src/analyzer/protocol/dns/DNS.h +++ b/src/analyzer/protocol/dns/DNS.h @@ -56,6 +56,7 @@ typedef enum { TYPE_EDNS = 41, ///< OPT pseudo-RR (RFC 2671) TYPE_TKEY = 249, ///< Transaction Key (RFC 2930) TYPE_TSIG = 250, ///< Transaction Signature (RFC 2845) + TYPE_CAA = 257, ///< Certification Authority Authorization (RFC 6844) // The following are only valid in queries. TYPE_AXFR = 252, @@ -211,6 +212,9 @@ protected: int ParseRR_TXT(DNS_MsgInfo* msg, const u_char*& data, int& len, int rdlength, const u_char* msg_start); + int ParseRR_CAA(DNS_MsgInfo* msg, + const u_char*& data, int& len, int rdlength, + const u_char* msg_start); int ParseRR_TSIG(DNS_MsgInfo* msg, const u_char*& data, int& len, int rdlength, const u_char* msg_start); diff --git a/src/analyzer/protocol/dns/events.bif b/src/analyzer/protocol/dns/events.bif index 9350939a2e..ae796c8e4c 100644 --- a/src/analyzer/protocol/dns/events.bif +++ b/src/analyzer/protocol/dns/events.bif @@ -378,6 +378,25 @@ event dns_MX_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string, ## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, strs: string_vec%); +## Generated for DNS replies of type *CAA* (Certification Authority Authorization). +## For replies with multiple answers, an individual event of the corresponding type +## is raised for each. +## See `RFC 6844 `__ for more details. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## flags: The flags byte of the CAA reply. +## +## tag: The property identifier of the CAA reply. +## +## value: The property value of the CAA reply. +event dns_CAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, flags: count, tag: string, value: string%); + ## Generated for DNS replies of type *SRV*. For replies with multiple answers, ## an individual event of the corresponding type is raised for each. ##