initial commit for SVCB/HTTPS records

This commit is contained in:
FlyingWithJerome 2021-09-29 10:24:16 -04:00
parent 4d48272adb
commit 8fce51bf83
9 changed files with 157 additions and 2 deletions

18
.vscode/c_cpp_properties.json vendored Normal file
View file

@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${default}",
"${workspaceFolder}/**"
],
"defines": [],
"macFrameworkPath": [],
"compilerPath": "/usr/local/bin/gcc-11",
"cStandard": "gnu17",
"cppStandard": "gnu++17",
"intelliSenseMode": "macos-gcc-x64"
}
],
"version": 4
}

5
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"files.associations": {
"thread": "cpp"
}
}

@ -1 +1 @@
Subproject commit ca0ff296b116354957276cef2c61be171ac2f897 Subproject commit 2361494e0400d52eb76d2c6c62db72168ebe69d0

2
doc

@ -1 +1 @@
Subproject commit fefd7e6ceb67dd011c268c658171967f1281b970 Subproject commit f562d75aef2e7c401913de122e4f888d42ae5f8e

View file

@ -3884,6 +3884,12 @@ type dns_loc_rr: record {
is_query: count; ##< The RR is a query/Response. is_query: count; ##< The RR is a query/Response.
}; };
type dns_svcb_rr: record {
svc_priority: count; ##< Service priority. (AliasMode? ServiceMode?)
target_name: string; ##< Target name, the hostname of the service endpoint.
svc_params: table[count] of vector of string; ##< service parameters as key-value pairs
}
# DNS answer types. # DNS answer types.
# #
# .. zeek:see:: dns_answerr # .. zeek:see:: dns_answerr

View file

@ -172,4 +172,15 @@ export {
[4] = "SHA384", [4] = "SHA384",
} &default = function(n: count): string { return fmt("digest-%d", n); }; } &default = function(n: count): string { return fmt("digest-%d", n); };
## SVCB/HTTPS SvcParam keys,
## as defined in https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-07.txt, sec 14.3.2
const svcparam_keys = {
[0] = "mandatory",
[1] = "alpn",
[2] = "no-default-alpn",
[3] = "port",
[4] = "ipv4hint",
[5] = "ech",
[6] = "ipv6hint",
} &default = function(n: count): string { return fmt("key%d", n); };
} }

View file

@ -345,6 +345,14 @@ bool DNS_Interpreter::ParseAnswer(detail::DNS_MsgInfo* msg, const u_char*& data,
status = ParseRR_LOC(msg, data, len, rdlength, msg_start); status = ParseRR_LOC(msg, data, len, rdlength, msg_start);
break; break;
case detail::TYPE_SVCB:
status = ParseRR_SVCB(msg, data, len, rdlength, msg_start, TYPE_SVCB);
break;
case detail::TYPE_HTTPS:
status = ParseRR_SVCB(msg, data, len, rdlength, msg_start, TYPE_HTTPS);
break;
default: default:
if ( dns_unknown_reply && ! msg->skip_event ) if ( dns_unknown_reply && ! msg->skip_event )
@ -1687,6 +1695,39 @@ bool DNS_Interpreter::ParseRR_CAA(detail::DNS_MsgInfo* msg, const u_char*& data,
return rdlength == 0; return rdlength == 0;
} }
bool DNS_Interpreter::ParseRR_SVCB(detail::DNS_MsgInfo* msg, const u_char*& data, int& len,
int rdlength, const u_char* msg_start, const RR_Type& svcb_type)
{
unsigned short svc_priority = ExtractShort(data, len);
u_char target_name[513];
int name_len = sizeof(target_name) - 1;
u_char* name_end = ExtractName(data, len, target_name, name_len, msg_start, false);
if ( ! name_end )
return false;
SVCB_DATA svcb_data = {
.svc_priority = svc_priority,
.target_name = new String(target_name, name_end - target_name, true),
.svc_params = nullptr,
};
// TODO: parse svcparams
switch( svcb_type )
{
case detail::TYPE_SVCB:
analyzer->EnqueueConnEvent(dns_SVCB, analyzer->ConnVal(), msg->BuildHdrVal(),
msg->BuildAnswerVal(), msg->BuildSVCB_Val(&svcb_data));
break;
case detail::TYPE_HTTPS:
analyzer->EnqueueConnEvent(dns_HTTPS, analyzer->ConnVal(), msg->BuildHdrVal(),
msg->BuildAnswerVal(), msg->BuildSVCB_Val(&svcb_data));
break;
}
return true;
}
void DNS_Interpreter::SendReplyOrRejectEvent(detail::DNS_MsgInfo* msg, EventHandlerPtr event, void DNS_Interpreter::SendReplyOrRejectEvent(detail::DNS_MsgInfo* msg, EventHandlerPtr event,
const u_char*& data, int& len, String* question_name, const u_char*& data, int& len, String* question_name,
String* original_name) String* original_name)
@ -1987,6 +2028,18 @@ RecordValPtr DNS_MsgInfo::BuildLOC_Val(LOC_DATA* loc)
return r; return r;
} }
RecordValPtr DNS_MsgInfo::BuildSVCB_Val(SVCB_DATA* svcb)
{
static auto dns_svcb_rr = id::find_type<RecordType>("dns_svcb_rr");
auto r = make_intrusive<RecordVal>(dns_svcb_rr);
r->Assign(0, svcb->svc_priority);
r->Assign(1, make_intrusive<StringVal>(svcb->target_name));
// TODO: assign svcparams
return dns_svcb_rr;
}
} // namespace detail } // namespace detail
Contents_DNS::Contents_DNS(Connection* conn, bool orig, detail::DNS_Interpreter* arg_interp) Contents_DNS::Contents_DNS(Connection* conn, bool orig, detail::DNS_Interpreter* arg_interp)

View file

@ -71,6 +71,8 @@ enum RR_Type
TYPE_DS = 43, ///< Delegation signer (RFC 4034) TYPE_DS = 43, ///< Delegation signer (RFC 4034)
TYPE_NSEC3 = 50, TYPE_NSEC3 = 50,
TYPE_NSEC3PARAM = 51, ///< Contains the NSEC3 parameters (RFC 5155) TYPE_NSEC3PARAM = 51, ///< Contains the NSEC3 parameters (RFC 5155)
TYPE_SVCB = 64, ///< SerViCe Binding (RFC draft: https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-07#section-1.1)
TYPE_HTTPS = 65, ///< HTTPS record (HTTPS specific SVCB resource record)
// Obsoleted // Obsoleted
TYPE_SPF = 99, ///< Alternative: storing SPF data in TXT records, using the same format (RFC TYPE_SPF = 99, ///< Alternative: storing SPF data in TXT records, using the same format (RFC
///< 4408). Support for it was discontinued in RFC 7208 ///< 4408). Support for it was discontinued in RFC 7208
@ -148,6 +150,18 @@ enum DNSSEC_Digest
SHA384 = 4, SHA384 = 4,
}; };
///< all keys are defined in RFC draft https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-07#section-14.3.2
enum SVCPARAM_Key
{
mandatory = 0,
alpn = 1,
no_default_alpn = 2,
port = 3,
ipv4hint = 4,
ech = 5,
ipv6hint = 6,
};
struct DNS_RawMsgHdr struct DNS_RawMsgHdr
{ {
unsigned short id; unsigned short id;
@ -269,6 +283,20 @@ struct LOC_DATA
unsigned long altitude; // 32 unsigned long altitude; // 32
}; };
struct SVCB_DATA
{
unsigned short svc_priority; // 2
String* target_name;
SVCPARAM_KV* svc_params;
}
struct SVCPARAM_KV
{
String* key;
String* value;
SVCPARAM_KV* next;
};
class DNS_MsgInfo class DNS_MsgInfo
{ {
public: public:
@ -288,6 +316,7 @@ public:
RecordValPtr BuildDS_Val(struct DS_DATA*); RecordValPtr BuildDS_Val(struct DS_DATA*);
RecordValPtr BuildBINDS_Val(struct BINDS_DATA*); RecordValPtr BuildBINDS_Val(struct BINDS_DATA*);
RecordValPtr BuildLOC_Val(struct LOC_DATA*); RecordValPtr BuildLOC_Val(struct LOC_DATA*);
RecordValPtr BuildSVCB_Val(struct SVCB_DATA*);
int id; int id;
int opcode; ///< query type, see DNS_Opcode int opcode; ///< query type, see DNS_Opcode
@ -393,6 +422,8 @@ protected:
const u_char* msg_start); const u_char* msg_start);
bool ParseRR_LOC(detail::DNS_MsgInfo* msg, const u_char*& data, int& len, int rdlength, bool ParseRR_LOC(detail::DNS_MsgInfo* msg, const u_char*& data, int& len, int rdlength,
const u_char* msg_start); const u_char* msg_start);
bool ParseRR_SVCB(detail::DNS_MsgInfo* msg, const u_char*& data, int& len, int rdlength,
const u_char* msg_start, const RR_Type& svcb_type);
void SendReplyOrRejectEvent(detail::DNS_MsgInfo* msg, EventHandlerPtr event, void SendReplyOrRejectEvent(detail::DNS_MsgInfo* msg, EventHandlerPtr event,
const u_char*& data, int& len, String* question_name, const u_char*& data, int& len, String* question_name,
String* original_name); String* original_name);

View file

@ -721,6 +721,37 @@ event dns_SSHFP%(c: connection, msg: dns_msg, ans: dns_answer, algo: count, fpty
## loc: The parsed RDATA of LOC type record. ## loc: The parsed RDATA of LOC type record.
event dns_LOC%(c: connection, msg: dns_msg, ans: dns_answer, loc: dns_loc_rr%); event dns_LOC%(c: connection, msg: dns_msg, ans: dns_answer, loc: dns_loc_rr%);
## Generated for DNS replies of type *SVCB*.
## See `RFC draft <https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-07>`__
## for more information about the DNS SVCB/HTTPS resource records.
## For replies with multiple answers, an individual event of the corresponding type is raised for each.
##
## 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.
##
## svcb: The parsed RDATA of SVCB type record.
event dns_SVCB%(c: connection, msg: dns_msg, ans: dns_answer, svcb: dns_svcb_rr%);
## Generated for DNS replies of type *HTTPS*.
## See `RFC draft <https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-07>`__
## for more information about the DNS SVCB/HTTPS resource records.
## Since SVCB and HTTPS record share the same wire format layout, the argument https is dns_svcb_rr.
## For replies with multiple answers, an individual event of the corresponding type is raised for each.
##
## 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.
##
## https: The parsed RDATA of SVCB type record.
event dns_HTTPS%(c: connection, msg: dns_msg, ans: dns_answer, https: dns_svcb_rr%);
## Generated at the end of processing a DNS packet. This event is the last ## Generated at the end of processing a DNS packet. This event is the last
## ``dns_*`` event that will be raised for a DNS query/reply and signals that ## ``dns_*`` event that will be raised for a DNS query/reply and signals that
## all resource records have been passed on. ## all resource records have been passed on.