mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Merge branch 'master' of https://github.com/FlyingWithJerome/zeek
Merge includes small changes, e.g. fixing the comsumption of remaining raw data. * 'master' of https://github.com/FlyingWithJerome/zeek: remove excussive fields in dns_svcb_rr address code reviews (formatting and type and intrusiveptr) newlines at the end of test outputs lazy commit use tabs in init-bare.zeek add svcb test case add a dns https test case remove test logs fix a few syntax errors initial commit for SVCB/HTTPS records
This commit is contained in:
commit
303e84ad86
14 changed files with 180 additions and 1 deletions
4
CHANGES
4
CHANGES
|
@ -1,3 +1,7 @@
|
|||
4.2.0-dev.271 | 2021-10-19 14:54:56 +0200
|
||||
|
||||
* Add parsing of DNS SVCB/HTTPS records (FlyingWithJerome)
|
||||
|
||||
4.2.0-dev.260 | 2021-10-15 09:45:45 +0100
|
||||
|
||||
* logging/writers/ascii: shadow files: Add fsync() before rename(). This
|
||||
|
|
3
NEWS
3
NEWS
|
@ -35,6 +35,9 @@ New Functionality
|
|||
specifying ``-O ZAM`` on the command line. See
|
||||
``src/script_opt/ZAM/README.md`` for more information.
|
||||
|
||||
- The DNS analyzer has initial support for the SVCB and HTTPS types. The new events
|
||||
are ``dns_SVCB`` and ``dns_HTTPS``.
|
||||
|
||||
Changed Functionality
|
||||
---------------------
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
4.2.0-dev.260
|
||||
4.2.0-dev.271
|
||||
|
|
|
@ -3884,6 +3884,14 @@ type dns_loc_rr: record {
|
|||
is_query: count; ##< The RR is a query/Response.
|
||||
};
|
||||
|
||||
## DNS SVCB and HTTPS RRs
|
||||
##
|
||||
## .. zeek:see:: dns_SVCB dns_HTTPS
|
||||
type dns_svcb_rr: record {
|
||||
svc_priority: count; ##< Service priority for the current record, 0 indicates that this record is in AliasMode and cannot carry svc_params; otherwise this is in ServiceMode, and may include svc_params
|
||||
target_name: string; ##< Target name, the hostname of the service endpoint.
|
||||
};
|
||||
|
||||
# DNS answer types.
|
||||
#
|
||||
# .. zeek:see:: dns_answerr
|
||||
|
|
|
@ -172,4 +172,15 @@ export {
|
|||
[4] = "SHA384",
|
||||
} &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); };
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
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:
|
||||
|
||||
if ( dns_unknown_reply && ! msg->skip_event )
|
||||
|
@ -1687,6 +1695,65 @@ bool DNS_Interpreter::ParseRR_CAA(detail::DNS_MsgInfo* msg, const u_char*& data,
|
|||
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)
|
||||
{
|
||||
const u_char* data_start = data;
|
||||
// the smallest SVCB/HTTPS rr is 3 bytes:
|
||||
// the first 2 bytes are for the svc priority, and the third byte is root (0x0)
|
||||
if ( len < 3 )
|
||||
{
|
||||
analyzer->Weird("DNS_SVBC_wrong_length");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t 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;
|
||||
|
||||
// target name can be root - in this case the alternative endpoint is
|
||||
// qname itself. make sure that we print "." instead of an empty string
|
||||
if ( name_end - target_name == 0 )
|
||||
{
|
||||
target_name[0] = '.';
|
||||
target_name[1] = '\0';
|
||||
name_end = target_name+1;
|
||||
}
|
||||
|
||||
SVCB_DATA svcb_data = {
|
||||
.svc_priority = svc_priority,
|
||||
.target_name = make_intrusive<StringVal>(new String(target_name, name_end - target_name, true)),
|
||||
};
|
||||
|
||||
// TODO: parse svcparams
|
||||
// we consume all the remaining raw data (svc params) but do nothing.
|
||||
// this should be removed if the svc param parser is ready
|
||||
std::ptrdiff_t parsed_bytes = data - data_start;
|
||||
if ( parsed_bytes < rdlength )
|
||||
{
|
||||
len -= ( rdlength - parsed_bytes );
|
||||
data += ( rdlength - parsed_bytes );
|
||||
}
|
||||
|
||||
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;
|
||||
default: break; // unreachable. for suppressing compiler warnings.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DNS_Interpreter::SendReplyOrRejectEvent(detail::DNS_MsgInfo* msg, EventHandlerPtr event,
|
||||
const u_char*& data, int& len, String* question_name,
|
||||
String* original_name)
|
||||
|
@ -1987,6 +2054,18 @@ RecordValPtr DNS_MsgInfo::BuildLOC_Val(LOC_DATA* loc)
|
|||
return r;
|
||||
}
|
||||
|
||||
RecordValPtr DNS_MsgInfo::BuildSVCB_Val(const 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, svcb.target_name);
|
||||
|
||||
// TODO: assign values to svcparams
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
Contents_DNS::Contents_DNS(Connection* conn, bool orig, detail::DNS_Interpreter* arg_interp)
|
||||
|
|
|
@ -71,6 +71,8 @@ enum RR_Type
|
|||
TYPE_DS = 43, ///< Delegation signer (RFC 4034)
|
||||
TYPE_NSEC3 = 50,
|
||||
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
|
||||
TYPE_SPF = 99, ///< Alternative: storing SPF data in TXT records, using the same format (RFC
|
||||
///< 4408). Support for it was discontinued in RFC 7208
|
||||
|
@ -148,6 +150,18 @@ enum DNSSEC_Digest
|
|||
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
|
||||
{
|
||||
unsigned short id;
|
||||
|
@ -269,6 +283,12 @@ struct LOC_DATA
|
|||
unsigned long altitude; // 32
|
||||
};
|
||||
|
||||
struct SVCB_DATA
|
||||
{
|
||||
uint16_t svc_priority; // 2
|
||||
StringValPtr target_name;
|
||||
};
|
||||
|
||||
class DNS_MsgInfo
|
||||
{
|
||||
public:
|
||||
|
@ -288,6 +308,7 @@ public:
|
|||
RecordValPtr BuildDS_Val(struct DS_DATA*);
|
||||
RecordValPtr BuildBINDS_Val(struct BINDS_DATA*);
|
||||
RecordValPtr BuildLOC_Val(struct LOC_DATA*);
|
||||
RecordValPtr BuildSVCB_Val(const struct SVCB_DATA&);
|
||||
|
||||
int id;
|
||||
int opcode; ///< query type, see DNS_Opcode
|
||||
|
@ -393,6 +414,8 @@ protected:
|
|||
const u_char* msg_start);
|
||||
bool ParseRR_LOC(detail::DNS_MsgInfo* msg, const u_char*& data, int& len, int rdlength,
|
||||
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,
|
||||
const u_char*& data, int& len, String* question_name,
|
||||
String* original_name);
|
||||
|
|
|
@ -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.
|
||||
event dns_LOC%(c: connection, msg: dns_msg, ans: dns_answer, loc: dns_loc_rr%);
|
||||
|
||||
## Generated for DNS replies of type *SVCB* (General Purpose Service Endpoints).
|
||||
## See `RFC draft for DNS SVCB/HTTPS <https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-07>`__
|
||||
## for more information about 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* (HTTPS Specific Service Endpoints).
|
||||
## See `RFC draft for DNS SVCB/HTTPS <https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-07>`__
|
||||
## for more information about DNS SVCB/HTTPS resource records.
|
||||
## Since SVCB and HTTPS records 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 HTTPS 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
|
||||
## ``dns_*`` event that will be raised for a DNS query/reply and signals that
|
||||
## all resource records have been passed on.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
[svc_priority=1, target_name=.]
|
|
@ -0,0 +1 @@
|
|||
[svc_priority=0, target_name=foo.example.com]
|
BIN
testing/btest/Traces/dns-https.pcap
Normal file
BIN
testing/btest/Traces/dns-https.pcap
Normal file
Binary file not shown.
BIN
testing/btest/Traces/dns-svcb.pcap
Normal file
BIN
testing/btest/Traces/dns-svcb.pcap
Normal file
Binary file not shown.
9
testing/btest/scripts/base/protocols/dns/https.zeek
Normal file
9
testing/btest/scripts/base/protocols/dns/https.zeek
Normal file
|
@ -0,0 +1,9 @@
|
|||
# @TEST-EXEC: zeek -C -r $TRACES/dns-https.pcap %INPUT > output
|
||||
# @TEST-EXEC: btest-diff output
|
||||
|
||||
@load policy/protocols/dns/auth-addl
|
||||
|
||||
event dns_HTTPS(c: connection, msg: dns_msg, ans: dns_answer, https: dns_svcb_rr)
|
||||
{
|
||||
print https;
|
||||
}
|
9
testing/btest/scripts/base/protocols/dns/svcb.zeek
Normal file
9
testing/btest/scripts/base/protocols/dns/svcb.zeek
Normal file
|
@ -0,0 +1,9 @@
|
|||
# @TEST-EXEC: zeek -C -r $TRACES/dns-svcb.pcap %INPUT > output
|
||||
# @TEST-EXEC: btest-diff output
|
||||
|
||||
@load policy/protocols/dns/auth-addl
|
||||
|
||||
event dns_SVCB(c: connection, msg: dns_msg, ans: dns_answer, svcb: dns_svcb_rr)
|
||||
{
|
||||
print svcb;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue