From: Brian Wellington Date: Mon, 1 Jun 2020 18:32:03 +0000 (-0700) Subject: Improvements to dns.rdata.to_wire(). X-Git-Tag: v2.0.0rc1~130^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c6c0041169f4888ffd96e7ca3d69c8ed351b8cb0;p=thirdparty%2Fdnspython.git Improvements to dns.rdata.to_wire(). This does two things. 1) Makes the file parameter optional, removing the requirement that callers create an io.BytesIO object if all they want is the bytes. This is done by renaming all of the rdata subclass to_wire() methods to _to_wire(), and making dns.rdata.to_wire() create the io.BytesIO internally if needed, and then delegate to the subclass. 2) Add canonicalize=False parameter, allowing code reuse for conversion to wire format and conversion to hashable format. This also removes all of the rdata subclass to_digestable routines that are no longer needed, as dns.rdata.to_digestable will work for all rdata types. --- diff --git a/dns/dnssec.py b/dns/dnssec.py index f775086f..598e4869 100644 --- a/dns/dnssec.py +++ b/dns/dnssec.py @@ -18,7 +18,6 @@ """Common DNSSEC-related functions and constants.""" import hashlib -import io import struct import time import base64 @@ -90,12 +89,6 @@ def algorithm_to_text(value): return Algorithm.to_text(value) -def _to_rdata(record, origin): - s = io.BytesIO() - record.to_wire(s, origin=origin) - return s.getvalue() - - def key_id(key): """Return the key id (a 16-bit number) for the specified key. @@ -104,7 +97,7 @@ def key_id(key): Returns an ``int`` between 0 and 65535 """ - rdata = _to_rdata(key, None) + rdata = key.to_wire() if key.algorithm == Algorithm.RSAMD5: return (rdata[-3] << 8) + rdata[-2] else: @@ -166,7 +159,7 @@ def make_ds(name, key, algorithm, origin=None): if isinstance(name, str): name = dns.name.from_text(name, origin) dshash.update(name.canonicalize().to_wire()) - dshash.update(_to_rdata(key, origin)) + dshash.update(key.to_wire(origin=origin)) digest = dshash.digest() dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, algorithm) + \ @@ -397,7 +390,7 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) data = b'' - data += _to_rdata(rrsig, origin)[:18] + data += rrsig.to_wire(origin=origin)[:18] data += rrsig.signer.to_digestable(origin) if rrsig.labels < len(rrname) - 1: diff --git a/dns/name.py b/dns/name.py index adf39c1b..fb64f428 100644 --- a/dns/name.py +++ b/dns/name.py @@ -590,19 +590,10 @@ class Name(object): Returns a ``bytes``. """ - out = bytearray() - for label in self.labels: - out.append(len(label)) - out += label.lower() - if not self.is_absolute(): - if origin is None or not origin.is_absolute(): - raise NeedAbsoluteNameOrOrigin - for label in origin.labels: - out.append(len(label)) - out += label.lower() - return bytes(out) + return self.to_wire(origin=origin, canonicalize=True) - def to_wire(self, file=None, compress=None, origin=None): + def to_wire(self, file=None, compress=None, origin=None, + canonicalize=False): """Convert name to wire format, possibly compressing it. *file* is the file where the name is emitted (typically an @@ -619,6 +610,10 @@ class Name(object): relative and origin is not ``None``, then *origin* will be appended to it. + *canonicalize*, a ``bool``, indicates whether the name should + be canonicalized; that is, converted to a format suitable for + digesting in hashes. + Raises ``dns.name.NeedAbsoluteNameOrOrigin`` if the name is relative and no origin was provided. @@ -629,13 +624,19 @@ class Name(object): out = bytearray() for label in self.labels: out.append(len(label)) - out += label + if canonicalize: + out += label.lower() + else: + out += label if not self.is_absolute(): if origin is None or not origin.is_absolute(): raise NeedAbsoluteNameOrOrigin for label in origin.labels: out.append(len(label)) - out += label + if canonicalize: + out += label.lower() + else: + out += label return bytes(out) if not self.is_absolute(): @@ -666,7 +667,10 @@ class Name(object): l = len(label) file.write(struct.pack('!B', l)) if l > 0: - file.write(label) + if canonicalize: + file.write(label.lower()) + else: + file.write(label) def __len__(self): """The length of the name (in labels). diff --git a/dns/name.pyi b/dns/name.pyi index 2fc37ad0..446600b0 100644 --- a/dns/name.pyi +++ b/dns/name.pyi @@ -18,7 +18,8 @@ class Name: def to_text(self, omit_final_dot=False) -> str: ... def to_unicode(self, omit_final_dot=False, idna_codec=None) -> str: ... def to_digestable(self, origin=None) -> bytes: ... - def to_wire(self, file=None, compress=None, origin=None) -> Optional[bytes]: ... + def to_wire(self, file=None, compress=None, origin=None, + canonicalize=False) -> Optional[bytes]: ... def __add__(self, other : Name): ... def __sub__(self, other : Name): ... def split(self, depth) -> List[Tuple[str,str]]: ... diff --git a/dns/rdata.py b/dns/rdata.py index b8d65f14..be5d3dbd 100644 --- a/dns/rdata.py +++ b/dns/rdata.py @@ -166,22 +166,30 @@ class Rdata(object): raise NotImplementedError - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + raise NotImplementedError + + def to_wire(self, file=None, compress=None, origin=None, + canonicalize=False): """Convert an rdata to wire format. - Returns ``None``. + Returns a ``bytes`` or ``None``. """ - raise NotImplementedError + if file: + return self._to_wire(file, compress, origin, canonicalize) + else: + f = io.BytesIO() + self._to_wire(f, compress, origin, canonicalize) + return f.getvalue() def to_generic(self, origin=None): """Creates a dns.rdata.GenericRdata equivalent of this rdata. Returns a ``dns.rdata.GenericRdata``. """ - f = io.BytesIO() - self.to_wire(f, origin=origin) - return dns.rdata.GenericRdata(self.rdclass, self.rdtype, f.getvalue()) + return dns.rdata.GenericRdata(self.rdclass, self.rdtype, + self.to_wire(origin=origin)) def to_digestable(self, origin=None): """Convert rdata to a format suitable for digesting in hashes. This @@ -190,9 +198,7 @@ class Rdata(object): Returns a ``bytes``. """ - f = io.BytesIO() - self.to_wire(f, None, origin) - return f.getvalue() + return self.to_wire(origin=origin, canonicalize=True) def validate(self): """Check that the current contents of the rdata's fields are @@ -361,7 +367,7 @@ class GenericRdata(Rdata): 'generic rdata hex data has wrong length') return cls(rdclass, rdtype, data) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): file.write(self.data) @classmethod diff --git a/dns/rdata.pyi b/dns/rdata.pyi index 84eeb8f8..f394791f 100644 --- a/dns/rdata.pyi +++ b/dns/rdata.pyi @@ -1,9 +1,9 @@ -from typing import Dict, Tuple, Any, Optional +from typing import Dict, Tuple, Any, Optional, BinaryIO from .name import Name, IDNACodec class Rdata: def __init__(self): self.address : str - def to_wire(self, file, compress : Optional[Dict[Name,int]], origin : Optional[Name]) -> bytes: + def to_wire(self, file : Optional[BinaryIO], compress : Optional[Dict[Name,int]], origin : Optional[Name], canonicalize : Optional[bool]) -> Optional[bytes]: ... @classmethod def from_text(cls, rdclass : int, rdtype : int, tok, origin=None, relativize=True): diff --git a/dns/rdtypes/ANY/CAA.py b/dns/rdtypes/ANY/CAA.py index 8e598004..d498107e 100644 --- a/dns/rdtypes/ANY/CAA.py +++ b/dns/rdtypes/ANY/CAA.py @@ -53,7 +53,7 @@ class CAA(dns.rdata.Rdata): value = tok.get_string().encode() return cls(rdclass, rdtype, flags, tag, value) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): file.write(struct.pack('!B', self.flags)) l = len(self.tag) assert l < 256 diff --git a/dns/rdtypes/ANY/CERT.py b/dns/rdtypes/ANY/CERT.py index 1432295b..5e4ceb8c 100644 --- a/dns/rdtypes/ANY/CERT.py +++ b/dns/rdtypes/ANY/CERT.py @@ -97,7 +97,7 @@ class CERT(dns.rdata.Rdata): return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, certificate) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): prefix = struct.pack("!HHB", self.certificate_type, self.key_tag, self.algorithm) file.write(prefix) diff --git a/dns/rdtypes/ANY/CSYNC.py b/dns/rdtypes/ANY/CSYNC.py index e258fda7..66f2f31b 100644 --- a/dns/rdtypes/ANY/CSYNC.py +++ b/dns/rdtypes/ANY/CSYNC.py @@ -86,7 +86,7 @@ class CSYNC(dns.rdata.Rdata): windows.append((window, bitmap[0:octets])) return cls(rdclass, rdtype, serial, flags, windows) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): file.write(struct.pack('!IH', self.serial, self.flags)) for (window, bitmap) in self.windows: file.write(struct.pack('!BB', window, len(bitmap))) diff --git a/dns/rdtypes/ANY/DNAME.py b/dns/rdtypes/ANY/DNAME.py index 2499283c..2000d9b0 100644 --- a/dns/rdtypes/ANY/DNAME.py +++ b/dns/rdtypes/ANY/DNAME.py @@ -22,5 +22,5 @@ class DNAME(dns.rdtypes.nsbase.UncompressedNS): """DNAME record""" - def to_digestable(self, origin=None): - return self.target.to_digestable(origin) + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.target.to_wire(file, None, origin, canonicalize) diff --git a/dns/rdtypes/ANY/GPOS.py b/dns/rdtypes/ANY/GPOS.py index 4969509e..4e9e8192 100644 --- a/dns/rdtypes/ANY/GPOS.py +++ b/dns/rdtypes/ANY/GPOS.py @@ -85,7 +85,7 @@ class GPOS(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, latitude, longitude, altitude) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): l = len(self.latitude) assert l < 256 file.write(struct.pack('!B', l)) diff --git a/dns/rdtypes/ANY/HINFO.py b/dns/rdtypes/ANY/HINFO.py index e3efb51a..dc982f11 100644 --- a/dns/rdtypes/ANY/HINFO.py +++ b/dns/rdtypes/ANY/HINFO.py @@ -53,7 +53,7 @@ class HINFO(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, cpu, os) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): l = len(self.cpu) assert l < 256 file.write(struct.pack('!B', l)) diff --git a/dns/rdtypes/ANY/HIP.py b/dns/rdtypes/ANY/HIP.py index 8ac1d177..51e42ac9 100644 --- a/dns/rdtypes/ANY/HIP.py +++ b/dns/rdtypes/ANY/HIP.py @@ -67,14 +67,14 @@ class HIP(dns.rdata.Rdata): servers.append(server) return cls(rdclass, rdtype, hit, algorithm, key, servers) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): lh = len(self.hit) lk = len(self.key) file.write(struct.pack("!BBH", lh, self.algorithm, lk)) file.write(self.hit) file.write(self.key) for server in self.servers: - server.to_wire(file, None, origin) + server.to_wire(file, None, origin, False) @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): diff --git a/dns/rdtypes/ANY/ISDN.py b/dns/rdtypes/ANY/ISDN.py index 4df58ad2..37332321 100644 --- a/dns/rdtypes/ANY/ISDN.py +++ b/dns/rdtypes/ANY/ISDN.py @@ -62,7 +62,7 @@ class ISDN(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, address, subaddress) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): l = len(self.address) assert l < 256 file.write(struct.pack('!B', l)) diff --git a/dns/rdtypes/ANY/LOC.py b/dns/rdtypes/ANY/LOC.py index a346cacb..c8785acc 100644 --- a/dns/rdtypes/ANY/LOC.py +++ b/dns/rdtypes/ANY/LOC.py @@ -254,7 +254,7 @@ class LOC(dns.rdata.Rdata): return cls(rdclass, rdtype, latitude, longitude, altitude, size, hprec, vprec) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): milliseconds = (self.latitude[0] * 3600000 + self.latitude[1] * 60000 + self.latitude[2] * 1000 + diff --git a/dns/rdtypes/ANY/NSEC.py b/dns/rdtypes/ANY/NSEC.py index 7da00e9e..24936cbe 100644 --- a/dns/rdtypes/ANY/NSEC.py +++ b/dns/rdtypes/ANY/NSEC.py @@ -87,20 +87,12 @@ class NSEC(dns.rdata.Rdata): windows.append((window, bitmap[0:octets])) return cls(rdclass, rdtype, next, windows) - def to_wire(self, file, compress=None, origin=None): - self.next.to_wire(file, None, origin) + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.next.to_wire(file, None, origin, canonicalize) for (window, bitmap) in self.windows: file.write(struct.pack('!BB', window, len(bitmap))) file.write(bitmap) - def to_digestable(self, origin=None): - file = io.BytesIO() - file.write(self.next.to_digestable(origin)) - for (window, bitmap) in self.windows: - file.write(struct.pack('!BB', window, len(bitmap))) - file.write(bitmap) - return file.getvalue() - @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): (next, cused) = dns.name.from_wire(wire[: current + rdlen], current) diff --git a/dns/rdtypes/ANY/NSEC3.py b/dns/rdtypes/ANY/NSEC3.py index c41b8fa6..208f9e8c 100644 --- a/dns/rdtypes/ANY/NSEC3.py +++ b/dns/rdtypes/ANY/NSEC3.py @@ -125,7 +125,7 @@ class NSEC3(dns.rdata.Rdata): return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, windows) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): l = len(self.salt) file.write(struct.pack("!BBHB", self.algorithm, self.flags, self.iterations, l)) diff --git a/dns/rdtypes/ANY/NSEC3PARAM.py b/dns/rdtypes/ANY/NSEC3PARAM.py index f0d5bb10..d10321b3 100644 --- a/dns/rdtypes/ANY/NSEC3PARAM.py +++ b/dns/rdtypes/ANY/NSEC3PARAM.py @@ -60,7 +60,7 @@ class NSEC3PARAM(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, algorithm, flags, iterations, salt) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): l = len(self.salt) file.write(struct.pack("!BBHB", self.algorithm, self.flags, self.iterations, l)) diff --git a/dns/rdtypes/ANY/OPENPGPKEY.py b/dns/rdtypes/ANY/OPENPGPKEY.py index 0bf7ab43..ddcd055c 100644 --- a/dns/rdtypes/ANY/OPENPGPKEY.py +++ b/dns/rdtypes/ANY/OPENPGPKEY.py @@ -49,7 +49,7 @@ class OPENPGPKEY(dns.rdata.Rdata): key = base64.b64decode(b64) return cls(rdclass, rdtype, key) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): file.write(self.key) @classmethod diff --git a/dns/rdtypes/ANY/RP.py b/dns/rdtypes/ANY/RP.py index 9580929f..5c4cc59b 100644 --- a/dns/rdtypes/ANY/RP.py +++ b/dns/rdtypes/ANY/RP.py @@ -46,13 +46,9 @@ class RP(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, mbox, txt) - def to_wire(self, file, compress=None, origin=None): - self.mbox.to_wire(file, None, origin) - self.txt.to_wire(file, None, origin) - - def to_digestable(self, origin=None): - return self.mbox.to_digestable(origin) + \ - self.txt.to_digestable(origin) + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.mbox.to_wire(file, None, origin, canonicalize) + self.txt.to_wire(file, None, origin, canonicalize) @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): diff --git a/dns/rdtypes/ANY/RRSIG.py b/dns/rdtypes/ANY/RRSIG.py index c7b9e7a1..0ee1c067 100644 --- a/dns/rdtypes/ANY/RRSIG.py +++ b/dns/rdtypes/ANY/RRSIG.py @@ -113,23 +113,15 @@ class RRSIG(dns.rdata.Rdata): original_ttl, expiration, inception, key_tag, signer, signature) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): header = struct.pack('!HBBIIIH', self.type_covered, self.algorithm, self.labels, self.original_ttl, self.expiration, self.inception, self.key_tag) file.write(header) - self.signer.to_wire(file, None, origin) + self.signer.to_wire(file, None, origin, canonicalize) file.write(self.signature) - def to_digestable(self, origin=None): - return struct.pack('!HBBIIIH', self.type_covered, - self.algorithm, self.labels, - self.original_ttl, self.expiration, - self.inception, self.key_tag) + \ - self.signer.to_digestable(origin) + \ - self.signature - @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): header = struct.unpack('!HBBIIIH', wire[current: current + 18]) diff --git a/dns/rdtypes/ANY/SOA.py b/dns/rdtypes/ANY/SOA.py index bb502653..cd59ec0d 100644 --- a/dns/rdtypes/ANY/SOA.py +++ b/dns/rdtypes/ANY/SOA.py @@ -63,19 +63,13 @@ class SOA(dns.rdata.Rdata): return cls(rdclass, rdtype, mname, rname, serial, refresh, retry, expire, minimum) - def to_wire(self, file, compress=None, origin=None): - self.mname.to_wire(file, compress, origin) - self.rname.to_wire(file, compress, origin) + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.mname.to_wire(file, compress, origin, canonicalize) + self.rname.to_wire(file, compress, origin, canonicalize) five_ints = struct.pack('!IIIII', self.serial, self.refresh, self.retry, self.expire, self.minimum) file.write(five_ints) - def to_digestable(self, origin=None): - return self.mname.to_digestable(origin) + \ - self.rname.to_digestable(origin) + \ - struct.pack('!IIIII', self.serial, self.refresh, - self.retry, self.expire, self.minimum) - @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): (mname, cused) = dns.name.from_wire(wire[: current + rdlen], current) diff --git a/dns/rdtypes/ANY/SSHFP.py b/dns/rdtypes/ANY/SSHFP.py index 8f8d0ca4..1c5269fd 100644 --- a/dns/rdtypes/ANY/SSHFP.py +++ b/dns/rdtypes/ANY/SSHFP.py @@ -60,7 +60,7 @@ class SSHFP(dns.rdata.Rdata): fingerprint = binascii.unhexlify(fingerprint) return cls(rdclass, rdtype, algorithm, fp_type, fingerprint) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): header = struct.pack("!BB", self.algorithm, self.fp_type) file.write(header) file.write(self.fingerprint) diff --git a/dns/rdtypes/ANY/TLSA.py b/dns/rdtypes/ANY/TLSA.py index 7b39030f..c6db8623 100644 --- a/dns/rdtypes/ANY/TLSA.py +++ b/dns/rdtypes/ANY/TLSA.py @@ -63,7 +63,7 @@ class TLSA(dns.rdata.Rdata): cert = binascii.unhexlify(cert) return cls(rdclass, rdtype, usage, selector, mtype, cert) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): header = struct.pack("!BBB", self.usage, self.selector, self.mtype) file.write(header) file.write(self.cert) diff --git a/dns/rdtypes/ANY/URI.py b/dns/rdtypes/ANY/URI.py index c37ecdf1..77f89645 100644 --- a/dns/rdtypes/ANY/URI.py +++ b/dns/rdtypes/ANY/URI.py @@ -57,7 +57,7 @@ class URI(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, priority, weight, target.value) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): two_ints = struct.pack("!HH", self.priority, self.weight) file.write(two_ints) file.write(self.target) diff --git a/dns/rdtypes/ANY/X25.py b/dns/rdtypes/ANY/X25.py index 04c33206..ac61849e 100644 --- a/dns/rdtypes/ANY/X25.py +++ b/dns/rdtypes/ANY/X25.py @@ -47,7 +47,7 @@ class X25(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, address) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): l = len(self.address) assert l < 256 file.write(struct.pack('!B', l)) diff --git a/dns/rdtypes/CH/A.py b/dns/rdtypes/CH/A.py index 42b72e5b..fefbab63 100644 --- a/dns/rdtypes/CH/A.py +++ b/dns/rdtypes/CH/A.py @@ -44,15 +44,11 @@ class A(dns.rdtypes.mxbase.MXBase): tok.get_eol() return cls(rdclass, rdtype, address, domain) - def to_wire(self, file, compress=None, origin=None): - self.domain.to_wire(file, compress, origin) + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.domain.to_wire(file, compress, origin, canonicalize) pref = struct.pack("!H", self.address) file.write(pref) - def to_digestable(self, origin=None): - return self.domain.to_digestable(origin) + \ - struct.pack("!H", self.address) - @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): (domain, cused) = dns.name.from_wire(wire[:current + rdlen - 2], diff --git a/dns/rdtypes/IN/A.py b/dns/rdtypes/IN/A.py index 9476d475..461ce927 100644 --- a/dns/rdtypes/IN/A.py +++ b/dns/rdtypes/IN/A.py @@ -43,7 +43,7 @@ class A(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, address) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): file.write(dns.ipv4.inet_aton(self.address)) @classmethod diff --git a/dns/rdtypes/IN/AAAA.py b/dns/rdtypes/IN/AAAA.py index 658cc4b0..9751f82c 100644 --- a/dns/rdtypes/IN/AAAA.py +++ b/dns/rdtypes/IN/AAAA.py @@ -43,7 +43,7 @@ class AAAA(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, address) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): file.write(dns.ipv6.inet_aton(self.address)) @classmethod diff --git a/dns/rdtypes/IN/APL.py b/dns/rdtypes/IN/APL.py index 2481d62d..5facf05d 100644 --- a/dns/rdtypes/IN/APL.py +++ b/dns/rdtypes/IN/APL.py @@ -106,7 +106,7 @@ class APL(dns.rdata.Rdata): return cls(rdclass, rdtype, items) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): for item in self.items: item.to_wire(file) diff --git a/dns/rdtypes/IN/DHCID.py b/dns/rdtypes/IN/DHCID.py index c5e526ce..cd5d0745 100644 --- a/dns/rdtypes/IN/DHCID.py +++ b/dns/rdtypes/IN/DHCID.py @@ -50,7 +50,7 @@ class DHCID(dns.rdata.Rdata): data = base64.b64decode(b64) return cls(rdclass, rdtype, data) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): file.write(self.data) @classmethod diff --git a/dns/rdtypes/IN/IPSECKEY.py b/dns/rdtypes/IN/IPSECKEY.py index 674f5e99..24dc652e 100644 --- a/dns/rdtypes/IN/IPSECKEY.py +++ b/dns/rdtypes/IN/IPSECKEY.py @@ -94,7 +94,7 @@ class IPSECKEY(dns.rdata.Rdata): return cls(rdclass, rdtype, precedence, gateway_type, algorithm, gateway, key) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): header = struct.pack("!BBB", self.precedence, self.gateway_type, self.algorithm) file.write(header) @@ -105,7 +105,7 @@ class IPSECKEY(dns.rdata.Rdata): elif self.gateway_type == 2: file.write(dns.ipv6.inet_aton(self.gateway)) elif self.gateway_type == 3: - self.gateway.to_wire(file, None, origin) + self.gateway.to_wire(file, None, origin, False) else: raise ValueError('invalid gateway type') file.write(self.key) diff --git a/dns/rdtypes/IN/NAPTR.py b/dns/rdtypes/IN/NAPTR.py index c68efc38..c0afc943 100644 --- a/dns/rdtypes/IN/NAPTR.py +++ b/dns/rdtypes/IN/NAPTR.py @@ -77,22 +77,13 @@ class NAPTR(dns.rdata.Rdata): return cls(rdclass, rdtype, order, preference, flags, service, regexp, replacement) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): two_ints = struct.pack("!HH", self.order, self.preference) file.write(two_ints) _write_string(file, self.flags) _write_string(file, self.service) _write_string(file, self.regexp) - self.replacement.to_wire(file, compress, origin) - - def to_digestable(self, origin=None): - file = io.BytesIO() - two_ints = struct.pack("!HH", self.order, self.preference) - file.write(two_ints) - _write_string(file, self.flags) - _write_string(file, self.service) - _write_string(file, self.regexp) - return file.getvalue() + self.replacement.to_digestable(origin) + self.replacement.to_wire(file, compress, origin, canonicalize) @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): diff --git a/dns/rdtypes/IN/NSAP.py b/dns/rdtypes/IN/NSAP.py index d098b4d9..a42e5928 100644 --- a/dns/rdtypes/IN/NSAP.py +++ b/dns/rdtypes/IN/NSAP.py @@ -50,7 +50,7 @@ class NSAP(dns.rdata.Rdata): address = binascii.unhexlify(address.encode()) return cls(rdclass, rdtype, address) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): file.write(self.address) @classmethod diff --git a/dns/rdtypes/IN/PX.py b/dns/rdtypes/IN/PX.py index e11f2655..e8e0adac 100644 --- a/dns/rdtypes/IN/PX.py +++ b/dns/rdtypes/IN/PX.py @@ -50,16 +50,11 @@ class PX(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, preference, map822, mapx400) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): pref = struct.pack("!H", self.preference) file.write(pref) - self.map822.to_wire(file, None, origin) - self.mapx400.to_wire(file, None, origin) - - def to_digestable(self, origin=None): - return struct.pack("!H", self.preference) + \ - self.map822.to_digestable(origin) + \ - self.mapx400.to_digestable(origin) + self.map822.to_wire(file, None, origin, canonicalize) + self.mapx400.to_wire(file, None, origin, canonicalize) @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): diff --git a/dns/rdtypes/IN/SRV.py b/dns/rdtypes/IN/SRV.py index 8c08f0b0..2b46305f 100644 --- a/dns/rdtypes/IN/SRV.py +++ b/dns/rdtypes/IN/SRV.py @@ -53,16 +53,10 @@ class SRV(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, priority, weight, port, target) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): three_ints = struct.pack("!HHH", self.priority, self.weight, self.port) file.write(three_ints) - self.target.to_wire(file, compress, origin) - - def to_digestable(self, origin=None): - f = io.BytesIO() - f.write(struct.pack("!HHH", self.priority, self.weight, self.port)) - f.write(self.target.to_digestable(origin)) - return f.getvalue() + self.target.to_wire(file, compress, origin, canonicalize) @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): diff --git a/dns/rdtypes/IN/WKS.py b/dns/rdtypes/IN/WKS.py index 155f86be..a5641358 100644 --- a/dns/rdtypes/IN/WKS.py +++ b/dns/rdtypes/IN/WKS.py @@ -82,7 +82,7 @@ class WKS(dns.rdata.Rdata): bitmap = dns.rdata._truncate_bitmap(bitmap) return cls(rdclass, rdtype, address, protocol, bitmap) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): file.write(dns.ipv4.inet_aton(self.address)) protocol = struct.pack('!B', self.protocol) file.write(protocol) diff --git a/dns/rdtypes/dnskeybase.py b/dns/rdtypes/dnskeybase.py index 1099e394..cfa34c2a 100644 --- a/dns/rdtypes/dnskeybase.py +++ b/dns/rdtypes/dnskeybase.py @@ -69,7 +69,7 @@ class DNSKEYBase(dns.rdata.Rdata): key = base64.b64decode(b64) return cls(rdclass, rdtype, flags, protocol, algorithm, key) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): header = struct.pack("!HBB", self.flags, self.protocol, self.algorithm) file.write(header) file.write(self.key) diff --git a/dns/rdtypes/dnskeybase.pyi b/dns/rdtypes/dnskeybase.pyi index ee70691d..2588cf37 100644 --- a/dns/rdtypes/dnskeybase.pyi +++ b/dns/rdtypes/dnskeybase.pyi @@ -27,7 +27,7 @@ class DNSKEYBase(rdata.Rdata): relativize_to=None): ... - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): ... @classmethod diff --git a/dns/rdtypes/dsbase.py b/dns/rdtypes/dsbase.py index 8da007bc..4f082c7f 100644 --- a/dns/rdtypes/dsbase.py +++ b/dns/rdtypes/dsbase.py @@ -61,7 +61,7 @@ class DSBase(dns.rdata.Rdata): return cls(rdclass, rdtype, key_tag, algorithm, digest_type, digest) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): header = struct.pack("!HBB", self.key_tag, self.algorithm, self.digest_type) file.write(header) diff --git a/dns/rdtypes/euibase.py b/dns/rdtypes/euibase.py index db4e56b1..7756538c 100644 --- a/dns/rdtypes/euibase.py +++ b/dns/rdtypes/euibase.py @@ -59,7 +59,7 @@ class EUIBase(dns.rdata.Rdata): raise dns.exception.SyntaxError('Hex decoding error: %s' % str(ex)) return cls(rdclass, rdtype, data) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): file.write(self.eui) @classmethod diff --git a/dns/rdtypes/mxbase.py b/dns/rdtypes/mxbase.py index a238b511..eb5816b2 100644 --- a/dns/rdtypes/mxbase.py +++ b/dns/rdtypes/mxbase.py @@ -48,14 +48,10 @@ class MXBase(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, preference, exchange) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): pref = struct.pack("!H", self.preference) file.write(pref) - self.exchange.to_wire(file, compress, origin) - - def to_digestable(self, origin=None): - return struct.pack("!H", self.preference) + \ - self.exchange.to_digestable(origin) + self.exchange.to_wire(file, compress, origin, canonicalize) @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): @@ -77,13 +73,8 @@ class UncompressedMX(MXBase): is not compressed when converted to DNS wire format, and whose digestable form is not downcased.""" - def to_wire(self, file, compress=None, origin=None): - super(UncompressedMX, self).to_wire(file, None, origin) - - def to_digestable(self, origin=None): - f = io.BytesIO() - self.to_wire(f, None, origin) - return f.getvalue() + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + super()._to_wire(file, None, origin, False) class UncompressedDowncasingMX(MXBase): @@ -91,5 +82,5 @@ class UncompressedDowncasingMX(MXBase): """Base class for rdata that is like an MX record, but whose name is not compressed when convert to DNS wire format.""" - def to_wire(self, file, compress=None, origin=None): - super(UncompressedDowncasingMX, self).to_wire(file, None, origin) + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + super()._to_wire(file, None, origin, canonicalize) diff --git a/dns/rdtypes/nsbase.py b/dns/rdtypes/nsbase.py index aab57fa3..dbd01609 100644 --- a/dns/rdtypes/nsbase.py +++ b/dns/rdtypes/nsbase.py @@ -45,11 +45,8 @@ class NSBase(dns.rdata.Rdata): tok.get_eol() return cls(rdclass, rdtype, target) - def to_wire(self, file, compress=None, origin=None): - self.target.to_wire(file, compress, origin) - - def to_digestable(self, origin=None): - return self.target.to_digestable(origin) + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.target.to_wire(file, compress, origin, canonicalize) @classmethod def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): @@ -68,10 +65,5 @@ class UncompressedNS(NSBase): is not compressed when convert to DNS wire format, and whose digestable form is not downcased.""" - def to_wire(self, file, compress=None, origin=None): - super(UncompressedNS, self).to_wire(file, None, origin) - - def to_digestable(self, origin=None): - f = io.BytesIO() - self.to_wire(f, None, origin) - return f.getvalue() + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + self.target.to_wire(file, None, origin, False) diff --git a/dns/rdtypes/txtbase.py b/dns/rdtypes/txtbase.py index 1c15dbf5..ec061a18 100644 --- a/dns/rdtypes/txtbase.py +++ b/dns/rdtypes/txtbase.py @@ -76,7 +76,7 @@ class TXTBase(dns.rdata.Rdata): raise dns.exception.UnexpectedEnd return cls(rdclass, rdtype, strings) - def to_wire(self, file, compress=None, origin=None): + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): for s in self.strings: l = len(s) assert l < 256 diff --git a/tests/test_rdtypeanyeui.py b/tests/test_rdtypeanyeui.py index 625c0c3c..e8645820 100644 --- a/tests/test_rdtypeanyeui.py +++ b/tests/test_rdtypeanyeui.py @@ -15,7 +15,6 @@ # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. import unittest -from io import BytesIO import dns.rrset import dns.rdtypes.ANY.EUI48 @@ -89,9 +88,7 @@ class RdtypeAnyEUI48TestCase(unittest.TestCase): inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN, dns.rdatatype.EUI48, eui) - buff = BytesIO() - inst.to_wire(buff) - self.assertEqual(buff.getvalue(), eui) + self.assertEqual(inst.to_wire(), eui) def testFromWireOk(self): '''Valid wire format.''' @@ -188,9 +185,7 @@ class RdtypeAnyEUI64TestCase(unittest.TestCase): inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN, dns.rdatatype.EUI64, eui) - buff = BytesIO() - inst.to_wire(buff) - self.assertEqual(buff.getvalue(), eui) + self.assertEqual(inst.to_wire(), eui) def testFromWireOk(self): '''Valid wire format.'''