-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dns_msg: skip RDLENGTH_LENGTH field when skipping record #20857
base: master
Are you sure you want to change the base?
Conversation
0744a79
to
352c37d
Compare
Can you add your test vector to https://github.com/RIOT-OS/RIOT/blob/master/tests/net/gnrc_sock_dns/tests-with-config/01-run.py to prevent future regressions, please? I think just adding the hexdump in a |
Ugh I think that test is somewhat broken. All requests after the first --- a/tests/net/gnrc_sock_dns/tests-with-config/01-run.py
+++ b/tests/net/gnrc_sock_dns/tests-with-config/01-run.py
@@ -296,6 +296,7 @@ def testfunc(child):
run(test_success)
run(test_timeout)
+ run(test_success)
run(test_too_short_response)
run(test_qdcount_too_large1)
run(test_qdcount_too_large2) you'll find that the test isn't testing anything at all. (also on |
352c37d
to
3c8e44d
Compare
Yeah, I was surprised that there is no dedicated test for |
I created It currently only contains positive tests, but could/should be extended with malicious data in the future to better stress the parser. But IMHO that's out of the scope of a bugfix PR. |
rebased to to master because of #20860 |
5f5b6c7
to
bc8ce1c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO better to use example values in the tests (actual values have the tendency to get stuck, e.g.), other than that, I would ACK.
/* handle DNS Message Compression */ | ||
if (*bufpos >= 192) { | ||
if (*bufpos & 0xc0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what this change has to do with debug output, but I agree it is more clearer what is checked for. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea I first read this as bufpos >= 192
and was confused as to why compression would start once the answer reaches a certain size…
0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6f, 0x6f, | ||
0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, | ||
0x00, 0x1c, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x1c, | ||
0x00, 0x01, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x10, | ||
0x2a, 0x00, 0x14, 0x50, 0x40, 0x05, 0x08, 0x0b, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0e, | ||
}; | ||
const uint8_t addr[] = { | ||
0x2a, 0x00, 0x14, 0x50, 0x40, 0x05, 0x08, 0x0b, | ||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0e, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why you need to use and name specific company names and existing addresses in the tests? I think example.org
-based names and 2001:db8::/32
-prefixed addresses should also work and have less potential of hassle (may it be legal, technical or otherwise) later on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how to generate synthetic DNS response messages. Also having real-world test data in there is a good way to verify our implementation against what's out there (and previously triggered the bug) - I don't think there is copyright on DNS response messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how to generate synthetic DNS response messages.
scapy
? Alternatively, DNS is a well known format, so you should be able to switch out the bytes manully. Here's how I would do it with the scapy
shell for dns_msg
.
>>> dns = DNS(bytes([ 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
...: 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x6f, 0x6f,
...: 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
...: 0x00, 0x1c, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x1c,
...: 0x00, 0x01, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x10,
...: 0x2a, 0x00, 0x14, 0x50, 0x40, 0x05, 0x08, 0x0b,
...: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0e,]))
>>>
>>> dns.qd
<DNSQR qname='google.com.' qtype=AAAA qclass=IN |>
>>> dns.qd[0]
<DNSQR qname='google.com.' qtype=AAAA qclass=IN |>
>>> dns.qd[0].qname
b'google.com.'
>>> dns.qd[0].qname = 'example.org'
>>> dns.an[0]
<DNSRR rrname='google.com.' type=AAAA rclass=IN ttl=300 rdlen=16 rdata=2a00:1450:4005:80b::200e |>
>>> dns.an[0].rrname = 'example.org'
>>> dns.an[0].rdata = '2001:db8:4005:80b::200e'
>>> dns.an
<DNSRR rrname='example.org.' type=AAAA rclass=IN ttl=300 rdlen=16 rdata=2001:db8:4005:80b::200e |>
>>> bytes(dns)
b'\x00\x00\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\x07example\x03org\x00\x00\x1c\x00\x01\x07example\x03org\x00\x00\x1c\x00\x01\x00\x00\x01,\x00\x10 \x01\r\xb8@\x05\x08\x0b\x00\x00\x00\x00\x00\x00 \x0e'
>>> str([f"0x{b:02x}" for b in bytes(dns)]).replace("'", "").replace("[", "{").replace("]", "}")
'{0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00, 0x1c, 0x00, 0x01, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0x40, 0x05, 0x08, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0e}'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…but why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arghs, just realized that this did not compress the name... use
str([f"0x{b:02x}" for b in bytes(dns.compress())]).replace("'", "").replace("[", "{").replace("]", "}")
in the last line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a lot of busywork for no real gain.
Why not use real world DNS messages to test against?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…but why?
Because it is unnecessary meta-data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was unnecessary meta-data (two CNAME records) that made the parsing fail in the first place!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How? Your OP doesn't mention them. And even then, afair your original bug analysis it was the length of the CNAME record that caused the issue, not the value itself.
Contribution description
dns_msg
skips unknown records, but the length record length field was only added when the record was not skipped - this caused the next record to be started 2 bytes short.Testing procedure
enable DNS with DNS64 server
We can resolve an IPv4 host behind NAT64 now 🎉
Issues/PRs references
fixes #20355