paulc / dnslib

A Python library to encode/decode DNS wire-format packets
https://github.com/paulc/dnslib
BSD 2-Clause "Simplified" License
295 stars 84 forks source link

Having trouble adding DS record subclass #46

Closed rmbolger closed 1 year ago

rmbolger commented 1 year ago

I've been working on a change to add a DS record RD subclass over in rmbolger@801edf75f48b8eb637ae738dfbff62ffa8c7cb74. It has a very similar structure to the DNSKEY record. The main difference is that the DNSKEY has the public key encoded as Base64 whereas the DS has the digest value encoded as Hex.

At a basic level, it seems to be working. But when I attempt to test it in a way that adds multiple answers to a DNSRecord something is happening where all of the instances of the record get overwritten with a copy of first one seen. The easiest demonstration is comparing an actual dig query to the dnslib.client output. For example:

>dig example.org. DS

; <<>> DiG 9.17.15 <<>> example.org. DS
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.org.                   IN      DS

;; ANSWER SECTION:
example.org.            2121    IN      DS      3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org.            2121    IN      DS      3397 8 2 ED1168604BC6A14068B9905401E62698BB3663B6EC2073EBD3599B88 2A785BF6
example.org.            2121    IN      DS      31589 8 1 7B8370002875DDA781390A8E586C31493847D9BC
example.org.            2121    IN      DS      31589 8 2 3FDC4C11FA3AD3535EA8C1CE3EAF7BFA5CA9AE8A834D98FEE10085CF AEB625AA
example.org.            2121    IN      DS      37780 8 1 B4A5CCE8D82DC585E327E5896EAE82E0B9A76DC6
example.org.            2121    IN      DS      37780 8 2 D96AFA9022000D368B5F497877DF289A1E9A13A1AB1F97BC1BF4D5DE 16879134

Six unique results where the digest values may have whitespace within the hex text (allowed but not mandated by the RFC).

>python -m dnslib.client --query --hex --dig example.org. DS
;; Sending:
;; QUERY: ef2b01000001000000000000076578616d706c65036f726700002b0001
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61227
;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;example.org.                   IN      DS

;; Got answer:
;; RESPONSE: ef2b81800001000600000000076578616d706c65036f726700002b0001c00c002b000100000e1000187b6508017b8370002875dda781390a8e586c31493847d9bcc00c002b000100000e10002493940802d96afa9022000d368b5f497877df289a1e9a13a1ab1f97bc1bf4d5de16879134c00c002b000100000e10001893940801b4a5cce8d82dc585e327e5896eae82e0b9a76dc6c00c002b000100000e1000240d450802ed1168604bc6a14068b9905401e62698bb3663b6ec2073ebd3599b882a785bf6c00c002b000100000e1000180d450801dee10345942c98711eb058b25a749ee342fce1dcc00c002b000100000e1000247b6508023fdc4c11fa3ad3535ea8c1ce3eaf7bfa5ca9ae8a834d98fee10085cfaeb625aa
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61227
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;example.org.                   IN      DS
;; ANSWER SECTION:
example.org.            3600    IN      DS      3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org.            3600    IN      DS      3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org.            3600    IN      DS      3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org.            3600    IN      DS      3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org.            3600    IN      DS      3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC
example.org.            3600    IN      DS      3397 8 1 DEE10345942C98711EB058B25A749EE342FCE1DC

The first result matches the first result in the dig output. But the next 5 results are just clones of the first instead of their individual rdata. I've tried adding some debug logging in the DS.parse method but it seems to be parsing the unique packets normally.

I feel like I must be doing something wrong here, but I can't figure out what it is.

rmbolger commented 1 year ago

Sigh, Apparently, I'm an idiot and accidentally put a @classmethod decorator on the __init__ method. Please ignore me. On the plus side, I should have a PR ready soon.