Ticket #5453: add-ends0-dnssec-record-types-01a.patch
| File add-ends0-dnssec-record-types-01a.patch, 52.8 KB (added by BobNovas, 15 months ago) |
|---|
-
names/common.py
18 18 19 19 EMPTY_RESULT = (), (), () 20 20 21 class DnssecConfig(): 22 """ 23 Sets recDes and the DNSSEC parameters. See RFC's 4033, 4034 and 4035. 24 25 recDes (RD) - Recursion Desired. Not a DNSSEC parameter and does not require ednsEnabled, 26 but still nice to be able to control whether or not you're asking for recursion. 27 (bool) 28 29 ednsEnabled - EDNS Enabled adds an OPT record to the query. The OPT record contains a 30 version field that indicates the version of EDNS that you can handle. 31 Presently, only EDNS Version 0 is defined. 32 (bool) 33 34 maxUdpPktSz - The max size UDP packet (bytes) that your end-to-end network can handle 35 (on a modern network a reliable size is 1492, although up to 65535 is possible). 36 Requires ednsEnabled. 37 (int) 38 39 dnssecOK (DO) - Dnssec Ok. A bit that indicates you want DNSSEC RR's and validation 40 if the resolver validates. If DO is set, AD will be set in the response 41 if the answer validates. Requires ednsEnabled. 42 (bool) 43 44 chkDis (CD) - Checking Disabled. If DO and CD are set, a validating resolver won't do 45 validation but will return the DNSSEC RR's so that YOU can. 46 (bool) 47 48 version - sets the edns version level. Currently, only 0 is defined and supported. 49 (int) 50 51 authData (AD) - Authentic Data. If set in a response from a validating resolver that you can 52 trust, indicates that the validating resolver validated the answer. Requires 53 ednsEnabled and DO set. (See note below.) 54 (bool) 55 56 Note - RFC-4035 does not define AD for a query. However, most validating resolvers seem 57 to honor it set in a query and return AD set in a response to a query that validates. But 58 you should not to rely on this behavior - set DO instead. 59 """ 60 def __init__(self, 61 recDes=True, 62 ednsEnabled=False, 63 maxUdpPktSz=512, 64 dnssecOk=False, 65 chkDis=False, 66 version=0, 67 authData=False): 68 69 self.recDes = recDes 70 self.ednsEnabled = ednsEnabled 71 self.maxUdpPktSz = maxUdpPktSz 72 self.dnssecOk = dnssecOk 73 self.chkDis = chkDis 74 self.version = version 75 self.authData = authData 76 77 assert not self.ednsEnabled or 512 <= self.maxUdpPktSz <= 65535 78 assert version == 0 79 21 80 class ResolverBase: 22 81 """ 23 82 L{ResolverBase} is a base class for L{IResolver} implementations which … … 36 95 37 96 typeToMethod = None 38 97 39 def __init__(self ):98 def __init__(self, dnssecConfig=None): 40 99 self.typeToMethod = {} 41 100 for (k, v) in typeToMethod.items(): 42 101 self.typeToMethod[k] = getattr(self, v) 102 self.dnssecConfig = dnssecConfig 103 if self.dnssecConfig == None: 104 self.dnssecConfig = DnssecConfig() 43 105 44 45 106 def exceptionForCode(self, responseCode): 46 107 """ 47 108 Convert a response code (one of the possible values of … … 200 261 @see: twisted.names.client.lookupAllRecords 201 262 """ 202 263 return self._lookup(name, dns.IN, dns.ALL_RECORDS, timeout) 264 265 def lookupDNSKey(self, name, timeout=None): 266 """ 267 @see: twisted.names.client.lookupDNSKey 268 """ 269 return self._lookup(name, dns.IN, dns.DNSKEY, timeout) 203 270 204 271 def getHostByName(self, name, timeout = None, effort = 10): 205 272 """ … … 268 335 dns.MX: 'lookupMailExchange', 269 336 dns.TXT: 'lookupText', 270 337 dns.SPF: 'lookupSenderPolicy', 271 338 dns.DNSKEY:'lookupDNSKey', 272 339 dns.RP: 'lookupResponsibility', 273 340 dns.AFSDB: 'lookupAFSDatabase', 274 341 dns.SRV: 'lookupService', -
names/dns.py
15 15 __all__ = [ 16 16 'IEncodable', 'IRecord', 17 17 18 'A', 'A6', 'AAAA', 'AFSDB', 'CNAME', 'DNAME', ' HINFO',18 'A', 'A6', 'AAAA', 'AFSDB', 'CNAME', 'DNAME', 'DNSKEY', 'DS', 'HINFO', 19 19 'MAILA', 'MAILB', 'MB', 'MD', 'MF', 'MG', 'MINFO', 'MR', 'MX', 20 'NAPTR', 'NS', 'NULL', 'PTR', 'RP', 'SOA', 'SPF', 'SRV', 'TXT', 'WKS', 20 'NAPTR', 'NS', 'NSEC', 'NSEC3', 'NSEC3PARAM', 'NULL', 'OPT', 'PTR', 21 'RP', 'RRSIG', 'SOA', 'SPF', 'SRV', 'TXT', 'WKS', 21 22 22 23 'ANY', 'CH', 'CS', 'HS', 'IN', 23 24 … … 26 27 'EFORMAT', 'ENAME', 'ENOTIMP', 'EREFUSED', 'ESERVER', 27 28 28 29 'Record_A', 'Record_A6', 'Record_AAAA', 'Record_AFSDB', 'Record_CNAME', 29 'Record_DNAME', 'Record_HINFO', 'Record_MB', 'Record_MD', 'Record_MF', 30 'Record_DNAME', 'Record_DNSKEY', 'Record_DS', 'Record_HINFO', 'Record_MB', 31 'Record_MD', 'Record_MF', 30 32 'Record_MG', 'Record_MINFO', 'Record_MR', 'Record_MX', 'Record_NAPTR', 31 'Record_NS', 'Record_N ULL', 'Record_PTR', 'Record_RP', 'Record_SOA',32 'Record_S PF', 'Record_SRV', 'Record_TXT', 'Record_WKS', 'UnknownRecord',33 'Record_NS', 'Record_NSEC', 'Record_NSEC3', 'Record_NULL', 'Record_OPT', 'Record_PTR', 'Record_RP', 'Record_RRSIG', 34 'Record_SOA', 'Record_SPF', 'Record_SRV', 'Record_TXT', 'Record_WKS', 'UnknownRecord', 33 35 34 36 'QUERY_CLASSES', 'QUERY_TYPES', 'REV_CLASSES', 'REV_TYPES', 'EXT_QUERIES', 35 37 36 'Charstr', 'Message', 'Name', ' Query', 'RRHeader', 'SimpleRecord',38 'Charstr', 'Message', 'Name', 'OPTHeader', 'Query', 'RRHeader', 'SimpleRecord', 37 39 'DNSDatagramProtocol', 'DNSMixin', 'DNSProtocol', 38 40 39 41 'OK', 'OP_INVERSE', 'OP_NOTIFY', 'OP_QUERY', 'OP_STATUS', 'OP_UPDATE', … … 46 48 # System imports 47 49 import warnings 48 50 51 import re 52 49 53 import struct, random, types, socket 50 54 51 55 import cStringIO as StringIO … … 54 58 55 59 from zope.interface import implements, Interface, Attribute 56 60 61 from base64 import b64decode, b64encode 57 62 63 58 64 # Twisted imports 59 65 from twisted.internet import protocol, defer 60 66 from twisted.internet.error import CannotListenError 61 67 from twisted.python import log, failure 62 68 from twisted.python import util as tputil 63 69 from twisted.python import randbytes 70 from twisted.names.ser_num_arith import SNA, DateSNA 64 71 65 72 66 73 def randomSource(): … … 79 86 NAPTR = 35 80 87 A6 = 38 81 88 DNAME = 39 89 OPT = 41 90 DS = 43 91 RRSIG = 46 92 NSEC = 47 93 DNSKEY = 48 94 NSEC3 = 50 95 NSEC3PARAM = 51 96 82 97 SPF = 99 83 98 84 99 QUERY_TYPES = { … … 108 123 NAPTR: 'NAPTR', 109 124 A6: 'A6', 110 125 DNAME: 'DNAME', 111 SPF: 'SPF' 126 OPT: 'OPT', 127 DS: 'DS', 128 RRSIG: 'RRSIG', 129 NSEC: 'NSEC', 130 DNSKEY: 'DNSKEY', 131 NSEC3: 'NSEC3', 132 NSEC3PARAM: 'NSEC3PARAM', 133 SPF: 'SPF', 112 134 } 113 135 114 136 IXFR, AXFR, MAILB, MAILA, ALL_RECORDS = range(251, 256) … … 277 299 def __str__(self): 278 300 return self.string 279 301 280 281 282 302 class Name: 283 303 implements(IEncodable) 284 304 … … 370 390 371 391 def __str__(self): 372 392 return self.name 393 394 class Sigstr(object): 395 ''' 396 for signatures and keys. display as b64 encoded 397 ''' 398 implements(IEncodable) 399 400 def __init__(self, string=''): 401 if not isinstance(string, str): 402 raise ValueError("%r is not a string" % (string, )) 403 self.string = string #b64encoded string 404 405 def encode(self, strio, compDict=None): 406 ''' 407 Write the byte representation (the un-b64-encoded string) 408 to the file. 409 410 @type strio: file 411 @param srio: The byte representation of this signature or key 412 will be written to this file 413 414 @type compDict: dict 415 @param compDict: not used. 416 ''' 417 strio.write(b64decode(self.string)) 418 419 def decode(self, strio, length=None): 420 ''' 421 Decode a signature or a key. 373 422 423 @type strio: file 424 @param strio: Exactly length bytes will be read from this file 425 to decode the full signature or key 426 427 @type length: int 428 @param lenth: length must always be given. A signature or key 429 is always the last thing in an RR and so you can always determine 430 its length. 431 ''' 432 self.string = '' 433 if length == None: 434 return 435 436 assert isinstance(length, int) 437 buff = readPrecisely(strio, length) 438 self.string = b64encode(buff) 439 440 def __eq__(self, other): 441 if isinstance(other, Sigstr): 442 return self.string == other.string 443 return False 444 445 def __hash__(self): 446 return hash(self.string) 447 448 def __str__(self): 449 return self.string 450 451 452 class TypeBitmaps(object): 453 ''' 454 bitmap encoding scheme used by NSEC and NSEC3 RR's 455 to indicate the RRset types that exist at the 456 NSEC/NSEC3 RR's original owner name or hashed name. 457 See RFC 4034 and RFC 5155. 458 ''' 459 fmt = 'BB' 460 typeRegex = re.compile('TYPE(\d+)') 461 462 def __init__(self, string=''): 463 self.string = string 464 465 def encode(self, strio, compDict=None): 466 """ 467 Encode the string field, which consists of a set 468 of type names, into an NSEC/NSEC3 type bitmap. 469 470 @type strio: file 471 @param strio: the byte representation of the type bitmap 472 will be written to this file. 473 474 @type compDict: dict 475 @param compDict: not used. 476 """ 477 if not self.string: 478 return; 479 480 #get a sorted list of RR Type Values 481 mnus = self.string.split(' ') 482 mnuVals = [] 483 for mnu in mnus: 484 mnuVal = REV_TYPES.get(mnu, None) 485 if not mnuVal: 486 m = self.typeRegex.match(mnu) 487 if m.groups(): 488 mnuVal = int(m.group(1)) 489 assert mnuVal < 65536 490 else: 491 log.err("can't parse %s in %s" % (mnu, self.string, )) 492 continue; 493 mnuVals.append(mnuVal) 494 mnuVals.sort() 495 496 #convert that to a dict of windows and lists 497 windDict = {} 498 for v in mnuVals: 499 window = (v >> 8) & 0xFF 500 if window not in windDict: 501 windDict[window] = [] 502 windDict[window].append(v & 0xFF) 503 504 #have to sort the keys - they're not in order! 505 windows = windDict.keys() 506 windows.sort() 507 508 #create the bitmaps 509 bmap = bytearray() 510 for w in windows: 511 bmapseg = bytearray(32) 512 maxoff = 0 513 for v in windDict[w]: 514 vm1 = v - 1 515 off = vm1 >> 3 516 bit = vm1 & 0x7 517 msk = 1 << bit 518 bmapseg[off] |= msk 519 maxoff = max(off, maxoff) 520 bmapseg = bmapseg[0:maxoff+1] 521 bmap += chr(w) + chr(maxoff+1) + bmapseg 522 523 strio.write(str(bmap)) 524 525 def decode(self, strio, length=None): 526 """ 527 Decode an NSEC/NSEC3 type bitmap into a string 528 representation of type names. 529 """ 530 self.type_bitmaps = "" 531 if length == None: 532 return 533 534 type_bitmaps = bytearray() 535 l = struct.calcsize(self.fmt) 536 parsed_length = 0 537 while parsed_length < length: 538 buff = readPrecisely(strio, l) 539 wb_num, bm_len = struct.unpack(self.fmt, buff) 540 assert parsed_length + 2 + bm_len <= length 541 bm = readPrecisely(strio, bm_len) 542 byteNum = -1 543 for b in bm: 544 byteNum += 1 545 ob = ord(b) 546 if ob == 0: 547 continue 548 549 for v in range(8): 550 msk = 1<<v 551 if ob & msk: 552 val = wb_num*256 + byteNum*8 + v + 1 553 mnu = QUERY_TYPES.get(val, None) 554 if not mnu: 555 mnu = 'TYPE' + str(val) 556 type_bitmaps += (mnu + ' ') 557 558 parsed_length += 2 + bm_len 559 560 self.type_bitmaps = str(type_bitmaps[0:-1]) 561 562 def __eq__(self, other): 563 if isinstance(other, TypeBitmaps): 564 return self.string == other.string 565 return False 566 567 def __hash__(self): 568 return hash(self.string) 569 570 def __str__(self): 571 return self.string 572 573 374 574 class Query: 375 575 """ 376 576 Represent a single DNS query. … … 434 634 return 'Query(%r, %r, %r)' % (str(self.name), self.type, self.cls) 435 635 436 636 437 class RRHeader(tputil.FancyEqMixin): 637 638 class OPTHeader(tputil.FancyEqMixin): 438 639 """ 640 A OPT record header. 641 642 @cvar fmt: C{str} specifying the byte format of an OPT Header. 643 644 @ivar name: Root (0, 8-bits) 645 @ivar type: 41 (OPT Record) 646 @ivar payload: An object that implements the IEncodable interface 647 @ivar auth: Whether this header is authoritative or not. 648 """ 649 650 implements(IEncodable) 651 652 compareAttributes = ('name', 'type', 'payload', 'auth') 653 654 fmt = "!H" 655 656 name = None 657 type = None 658 payload = None 659 660 #OPTHeader _really_ has no ttl or rdlength, but the 661 #existence of the attributes is required. 662 ttl = None 663 rdlength = None 664 665 cachedResponse = None 666 667 def __init__(self, payload=None, auth=False): 668 """ 669 @type name: C{str} 670 @param name: Root (0) 671 672 @type type: C{int} 673 @param type: Query type 41. 674 675 @type payload: An object implementing C{IEncodable} 676 @param payload: The OPT payload 677 """ 678 assert (payload is None) or (payload.TYPE == OPT) 679 680 self.name = 0 681 self.type = OPT 682 self.payload = payload 683 self.auth = auth 684 685 def encode(self, strio, compDict=None): 686 strio.write(struct.pack('!B', 0)) 687 strio.write(struct.pack(self.fmt, self.type)) 688 if self.payload: 689 prefix = strio.tell() 690 self.payload.encode(strio, compDict) 691 aft = strio.tell() 692 strio.seek(prefix - 2, 0) 693 strio.write(struct.pack('!H', aft - prefix)) 694 strio.seek(aft, 0) 695 696 def decode(self, strio, length = None): 697 self.name.decode(strio) 698 l = struct.calcsize(self.fmt) 699 buff = readPrecisely(strio, l) 700 r = struct.unpack(self.fmt, buff) 701 self.type = r[0] 702 703 def isAuthoritative(self): 704 return self.auth 705 706 def __str__(self): 707 return '<OPT auth=%s>' % (self.auth and 'True' or 'False') 708 709 @staticmethod 710 def factory(strio, auth=False): 711 ''' 712 reads enough of the stream to figure out if what is there is 713 an OPTHeader or an RRHeader 714 ''' 715 beginPos = strio.tell() 716 name = Name() 717 name.decode(strio) 718 type = struct.unpack(OPTHeader.fmt, readPrecisely(strio, 2))[0] 719 720 if len(name.name) == 0 and type == OPT: 721 return OPTHeader() 722 else: 723 #back up to the beginning and try again 724 strio.seek(beginPos, 0) 725 rrh = RRHeader(auth=auth) 726 rrh.decode(strio) 727 rrh.auth = auth 728 return rrh 729 730 __repr__ = __str__ 731 732 733 class RRHeader(OPTHeader): 734 """ 439 735 A resource record header. 440 736 441 737 @cvar fmt: C{str} specifying the byte format of an RR. … … 1469 1765 return hash(tuple(self.data)) 1470 1766 1471 1767 1768 class Record_OPT(tputil.FancyEqMixin, tputil.FancyStrMixin): 1769 """ 1770 EDNS0 Option record. 1771 1772 @type payload_size: C{int} 1773 @ivar payload_size: Specifies the max UDP Packet size (bytes) that your 1774 network can handle. 1775 1776 @type dnssecOk: C{bool} 1777 @ivar dnssecOk: Requests the server to send DNSSEC RRs and to do DNSSEC 1778 validation (and set the AD bit if the response validates). 1779 1780 @type version: C{int} 1781 @ivar version: The version of DNSSEC used. Currently only version 0 1782 is defined. 1783 """ 1784 implements(IEncodable, IRecord) 1785 TYPE = OPT 1786 fmt = '!HBBHH' 1787 1788 fancybasename = 'OPT' 1789 showAttributes = ('payload_size', ('flags', 'flags', '0x%x'), 'version') 1790 compareAttributes = ('payload_size', 'flags', 'version') 1791 1792 def __init__(self, payload_size=512, dnssecOk=0, version=0, ttl=None): 1793 self.payload_size = payload_size 1794 self.version = version 1795 self.flags = (dnssecOk & 1) << 15 1796 1797 def encode(self, strio, compDict = None): 1798 OPTHeader().encode(strio) 1799 strio.write(struct.pack('!H', self.payload_size)) 1800 strio.write(struct.pack('!B', 0)) # high order 0 1801 strio.write(struct.pack('!B', self.version)) 1802 strio.write(struct.pack('!H', self.flags)) # DO(bit) + Z's 1803 strio.write(struct.pack('!H', 0)) # Data length: 0 1804 1805 def decode(self, strio, length=None): 1806 ''' 1807 are OPT Records always 0 rdlength? 1808 ''' 1809 l = struct.calcsize(self.fmt) 1810 buff = readPrecisely(strio, l) 1811 r = struct.unpack(self.fmt, buff) 1812 self.payload_size, z, self.version, self.flags, length = r 1813 assert length == 0 1814 1815 def __hash__(self): 1816 return hash((self.payload_size, self.version, self.flags)) 1472 1817 1818 class Record_RRSIG(tputil.FancyEqMixin, tputil.FancyStrMixin): 1819 """ 1820 DNSSEC RRSIG record. See RFC 4034 for details. 1821 1822 @type type_covered: C{int} 1823 @ivar type_covered: Identifies the type of the RRset that this RRSIG covers. 1824 1825 @type algo: C{int} 1826 @ivar algo: Identifies the crypto algorithm type used to create the signature. 1827 (5 - RSH/SHA-1 is mandatory. See RFC 4034 App A.1 for the full list.) 1828 1829 @type labels: C{int} 1830 @ivar labels: Specifies the number of labels in the original RRSIG RR owner name. 1831 A validator can use this to determine whether the answer was synthesized from 1832 a wildcard. 1833 1834 @type original_ttl: C{int} 1835 @ivar original_ttl: Specifies the TTL of the covered RRset as it appears in the 1836 authoritative zone. 1837 1838 @type sig_expiration: C{int} 1839 @ivar sig_expiration: This RRSIG must NOT be used after this time. Seconds 1840 since 1/1/1970, Modulo 2**32, compare using DNS Serial Number Arithmetic 1841 1842 @type sig_inception: C{int} 1843 @ivar sig_inception: This RRSIG must NOT be used prior to this time. Seconds 1844 since 1/1/1970, Modulo 2**32, compare using DNS Serial Number Arithmetic 1845 1846 @type key_tag: C{int} 1847 @ivar key_tag: Contains the key tag value of the DNSKEY RR that validates this 1848 signature, in network byte order. See RFC 4034 App B. 1849 1850 @type signers_name: L{Name} 1851 @ivar signers_name: Identifies the owner name of the DNSKEY RR that a validator 1852 should use to validate this signature. Must not use DNS name compression. 1853 1854 @type signature: L{Sigstr} 1855 @ivar signature: Contains the cryptographic signature that covers the RRSIG 1856 RDATA (excluding the Signature field and the RRset specified by the RRSIG 1857 owner name, RRSIG class and RRSIG Type Covered fields. 1858 1859 @type ttl: C{int} 1860 @ivar ttl: The maximum number of seconds which this record should be 1861 cached. 1862 """ 1863 implements(IEncodable, IRecord) 1864 TYPE = RRSIG 1865 fmt = '!HBBIIIH' 1866 1867 fancybasename = 'RRSIG' 1868 showAttributes = ('type_covered', 'algo', 'labels', 'original_ttl', 1869 ('_sig_expiration', 'sig_expiration', '%s'), 1870 ('_sig_inception', 'sig_inception', '%s'), 1871 'key_tag', 1872 ('signers_name', 'signers_name', '%s'), 1873 ('_signature', 'signature', '%s'), 'ttl') 1874 compareAttributes = ('type_covered', 'algo', 'labels', 'original_ttl', 1875 'sig_expiration', 'sig_inception', 'key_tag', 1876 'signers_name', 'signature', 'ttl') 1877 1878 _sig_expiration = property(lambda self: str(self.sig_expiration)) 1879 _sig_inception = property(lambda self: str(self.sig_inception)) 1880 _signature = property(lambda self: self.signature.string) 1881 1882 def __init__(self, type_covered=A, algo=0, labels=0, original_ttl=0, 1883 sig_expiration='', sig_inception='', key_tag=0, 1884 signers_name='', signature='', ttl=None): 1885 self.type_covered = type_covered 1886 self.algo = algo 1887 self.labels = labels 1888 self.original_ttl = original_ttl 1889 self.sig_expiration = DateSNA(sig_expiration) 1890 self.sig_inception = DateSNA(sig_inception) 1891 self.key_tag = key_tag 1892 self.signers_name = Name(signers_name) 1893 self.signature = Sigstr(signature) 1894 self.ttl = str2time(ttl) 1895 1896 def encode(self, strio, compDict = None): 1897 strio.write(struct.pack(self.fmt, 1898 self.type_covered, 1899 self.algo, 1900 self.labels, 1901 self.original_ttl, 1902 self.sig_expiration.asInt(), 1903 self.sig_inception.asInt(), 1904 self.key_tag)) 1905 self.signers_name.encode(strio, None) 1906 self.signature.encode(strio, compDict) 1907 1908 def decode(self, strio, length=None): 1909 start = strio.tell() 1910 l = struct.calcsize(self.fmt) 1911 buff = readPrecisely(strio, l) 1912 r = struct.unpack(self.fmt, buff) 1913 self.type_covered, self.algo, self.labels, self.original_ttl, \ 1914 sig_expiration, sig_inception, self.key_tag = r 1915 self.sig_expiration = DateSNA.fromInt(sig_expiration) 1916 self.sig_inception = DateSNA.fromInt(sig_inception) 1917 self.signers_name.decode(strio) 1918 here = strio.tell() 1919 self.signature.decode(strio, length + start - here if length else None) 1920 1921 def __hash__(self): 1922 return hash((self.type_covered, self.algo, self.labels, self.original_ttl, 1923 self.sig_expiration, self.sig_inception, self.key_tag, 1924 self.signers_name, self.signature)) 1925 1926 class Record_DS(tputil.FancyEqMixin, tputil.FancyStrMixin): 1927 """ 1928 A DNSSEC DS record. 1929 1930 @type key_tag: C{int} 1931 @ivar key_tag: Lists the key tag of the DNSKEY RR referred to by this DS record. 1932 1933 @type algo: C{int} 1934 @ivar algo: Lists the algorithm number of the DNSKEY RR referenced by this DS record. 1935 1936 @type digest_type: C{int} 1937 @ivar digest_type: Identifies the algorithm used to construct the digest field. 1938 1939 @type digest: L{Sigstr} 1940 @ivar digest: Contains a digest of the refeerenced DNSKEY RR calculated by the 1941 algorithm identified by the digest_type field. 1942 1943 @type ttl: C{int} 1944 @ivar ttl: The maximum number of seconds which this record should be 1945 cached. 1946 """ 1947 implements(IEncodable, IRecord) 1948 TYPE = DS 1949 fmt = '!HBB' 1950 1951 fancybasename = 'DS' 1952 showAttributes = ('key_tag', 'algo', 'digest_type', ('_digest', 'digest', '%s'), 'ttl') 1953 compareAttributes = ('key_tag', 'algo', 'digest_type', 'digest', 'ttl') 1954 1955 _digest = property(lambda self: self.digest.string) 1956 1957 def __init__(self, key_tag=0, algo=0, digest_type=0, digest='', ttl=None): 1958 self.key_tag = key_tag 1959 self.algo = algo 1960 self.digest_type = digest_type 1961 self.digest = Sigstr(digest) 1962 self.ttl = str2time(ttl) 1963 1964 def encode(self, strio, compDict = None): 1965 strio.write(struct.pack(self.fmt, 1966 self.key_tag, 1967 self.algo, 1968 self.digest_type)) 1969 self.digest.encode(strio, None) 1970 1971 def decode(self, strio, length=None): 1972 start = strio.tell() 1973 l = struct.calcsize(self.fmt) 1974 buff = readPrecisely(strio, l) 1975 r = struct.unpack(self.fmt, buff) 1976 self.key_tag, self.algo, self.digest_type = r 1977 here = strio.tell() 1978 self.digest.decode(strio, length + start - here if length else None) 1979 1980 def __hash__(self): 1981 return hash((self.key_tag, self.algo, self.digest_type, self.digest)) 1982 1983 class Record_DNSKEY(tputil.FancyEqMixin, tputil.FancyStrMixin): 1984 """ 1985 A DNSSEC DNSKEY record. Holds the public key for a signed RRset. 1986 1987 @type flags: C{int} 1988 @ivar flags: Bit 7 is the Zone Key flag. If bit 7 has value 1, then the 1989 DNSKEY record holds a DNS zone key and the DNSKEY RR's owner name is 1990 the name of a zone. If bit 7 has value 0, then the DNSKEY record 1991 holds some other type of DNS public key and MUST NOT be used to 1992 verify RRSIGs that cover RRsets. 1993 Bit 15 is the Secure Entry Point flag. See RFC 3757.) 1994 All other bits are reserved and must be zero. 1995 1996 @type protocol: C{int} 1997 @ivar protocol: Must have value 3. The DNSKEY RR must be treated as invalid 1998 if this field does not contain 3. 1999 2000 @type algo: C{int} 2001 @ivar algo: Identifies the public key's cryptographic algorithm and determines 2002 the format of the pub_key field. See RFC 4034 App A. 2003 2004 @type pub_key: L{Sigstr} 2005 @ivar pub_key: Holds the public key material. 2006 2007 @type ttl: C{int} 2008 @ivar ttl: The maximum number of seconds which this record should be 2009 cached. 2010 """ 2011 implements(IEncodable, IRecord) 2012 TYPE = DNSKEY 2013 fmt = '!HBB' 2014 2015 fancybasename = 'DNSKEY' 2016 showAttributes = ('flags', 'protocol', 'algo', ('_pub_key', 'pub_key', '%s'), 'ttl') 2017 compareAttributes = ('flags', 'protocol', 'algo', 'pub_key', 'ttl') 2018 2019 _pub_key = property(lambda self: self.pub_key.string) 2020 2021 def __init__(self, flags=0, protocol=0, algo=0, pub_key='', ttl=None): 2022 self.flags = flags 2023 self.protocol = protocol 2024 self.algo = algo 2025 self.pub_key = Sigstr(pub_key) 2026 self.ttl = str2time(ttl) 2027 2028 def encode(self, strio, compDict = None): 2029 strio.write(struct.pack(self.fmt, 2030 self.flags, 2031 self.protocol, 2032 self.algo)) 2033 self.pub_key.encode(strio, None) 2034 2035 def decode(self, strio, length=None): 2036 start = strio.tell() 2037 l = struct.calcsize(self.fmt) 2038 buff = readPrecisely(strio, l) 2039 r = struct.unpack(self.fmt, buff) 2040 self.flags, self.protocol, self.algo = r 2041 here = strio.tell() 2042 self.pub_key.decode(strio, length + start - here if length else None) 2043 2044 def __hash__(self): 2045 return hash((self.flags, self.protocol, self.algo, self.pub_key)) 2046 2047 class Record_NSEC(tputil.FancyEqMixin, tputil.FancyStrMixin): 2048 """ 2049 A DNSSEC NSEC record provides authenticated denial of existance for DNS data. 2050 2051 A DNSSEC NSEC record lists: 2052 2053 1) the next owner name in canonical ordering of the zone that contains authoritataive 2054 data or a delegation point NS RRset. 2055 2056 2) the set of RR types present at the NSEC RR's owner name. 2057 2058 @type nxt_name: L{Name} 2059 @ivar nxt_name: The next owner name that has authoritative data or contains a 2060 delegation point NS RRset. 2061 2062 @type type_bitmaps: L{TypeBitmaps} 2063 @ivar type_bitmaps: Identifies the RRset types that exist at the NSEC RR's owner name. 2064 2065 @type ttl: C{int} 2066 @ivar ttl: The maximum number of seconds which this record should be 2067 cached. 2068 """ 2069 implements(IEncodable, IRecord) 2070 TYPE = NSEC 2071 2072 fancybasename = 'NSEC' 2073 showAttributes = (('nxt_name', 'nxt_name', '%s'), ('_type_bitmaps', 'type_bitmaps', '%s'), 'ttl') 2074 compareAttributes = ('nxt_name', 'type_bitmaps', 'ttl') 2075 2076 _type_bitmaps = property(lambda self: self.type_bitmaps.string) 2077 2078 def __init__(self, nxt_name='', type_bitmaps=None, ttl=None): 2079 self.nxt_name = Name(nxt_name) 2080 self.type_bitmaps = TypeBitmaps(type_bitmaps) 2081 self.ttl = str2time(ttl) 2082 2083 def encode(self, strio, compDict = None): 2084 self.nxt_name.encode(strio, None) 2085 self.type_bitmaps.encode(strio, None) 2086 2087 def decode(self, strio, length=None): 2088 start = strio.tell() 2089 self.nxt_name.decode(strio, None) 2090 here = strio.tell() 2091 self.type_bitmaps.decode(strio, length + start - here if length else None) 2092 2093 def __hash__(self): 2094 return hash((self.nxt_name, self.type_bitmaps)) 2095 2096 class Record_NSEC3PARAM(tputil.FancyEqMixin, tputil.FancyStrMixin): 2097 """ 2098 A DNSSEC NSEC3PARAM record contains the NSEC3 parameters (hash algorithm, 2099 flags, iterations and salt) needed by authoritative servers to calculate 2100 hashed owner names. The presence of an NSEC3PARAM RR at a zone apex 2101 indicates that the specified parameters may be used by authoritative 2102 servers to choose an appropriate set of NSEC3 RRs for negative responses. 2103 2104 @type hash_algo: C{int} 2105 @ivar hash_algo: Identifies the cryptographic hash algorithm used to construct the hash value. 2106 2107 @type flags: C{int} 2108 @ivar flags: Identifies 8 1-bit flags. The only flag presently defined is the 2109 opt-out flag. If the opt-out flag is set, the NSEC3 record covers zero or more unsigned 2110 delegations. If the opt-out flag is clear, the NSEC3 record covers zero unsigned delegations. 2111 2112 @type iterations: C{int} 2113 @ivar iterations: Defines the nubmer of additional times the hash algorithm has been performed. 2114 2115 @type salt: L{Charset} 2116 @ivar salt: Identifies the salt value provided to the hash. 2117 2118 @type ttl: C{int} 2119 @ivar ttl: The maximum number of seconds which this record should be 2120 cached. 2121 """ 2122 implements(IEncodable, IRecord) 2123 TYPE = NSEC3 2124 fmt = '!BBH' 2125 2126 fancybasename = 'NSEC3' 2127 showAttributes = ('hash_algo', 'flags', 'iterations', ('_salt', 'salt', '%s'), 'ttl') 2128 compareAttributes = ('hash_algo', 'flags', 'iterations', 'salt', 'ttl') 2129 2130 _salt = property(lambda self: self.salt.string) 2131 2132 def __init__(self, hash_algo=0, flags=0, iterations=0, salt='', ttl=None): 2133 self.hash_algo = hash_algo 2134 self.flags = flags 2135 self.iterations = iterations 2136 self.salt = Charstr(salt) 2137 self.ttl = str2time(ttl) 2138 2139 def encode(self, strio, compDict = None): 2140 strio.write(struct.pack(self.fmt, 2141 self.hash_algo, 2142 self.flags, 2143 self.iterations)) 2144 self.salt.encode(strio, None) 2145 2146 def decode(self, strio, length=None): 2147 start = strio.tell() 2148 l = struct.calcsize(self.fmt) 2149 buff = readPrecisely(strio, l) 2150 r = struct.unpack(self.fmt, buff) 2151 self.hash_algo, self.flags, self.iterations = r 2152 self.salt.decode(strio) 2153 here = strio.tell() 2154 2155 def __hash__(self): 2156 return hash((self.hash_algo, self.flags, self.iterations, self.salt)) 2157 2158 class Record_NSEC3(Record_NSEC3PARAM): 2159 """ 2160 A DNSSEC NSEC3 record provides non-zone-enumerable authenticated denial of existance 2161 for DNS data and permits a gradual expansion of delegation-centric zones. 2162 2163 A DNSSEC NSEC3 record lists: 2164 2165 1) the set of RR types present at the original owner name of the NSEC RR. 2166 2167 2) the next hashed owner name in the hash order of the zone. 2168 2169 @type hash_algo: C{int} 2170 @ivar hash_algo: Identifies the cryptographic hash algorithm used to construct the hash value. 2171 2172 @type flags: C{int} 2173 @ivar flags: Identifies 8 1-bit flags. The only flag presently defined is the 2174 opt-out flag. If the opt-out flag is set, the NSEC3 record covers zero or more unsigned 2175 delegations. If the opt-out flag is clear, the NSEC3 record covers zero unsigned delegations. 2176 2177 @type iterations: C{int} 2178 @ivar iterations: Defines the nubmer of additional times the hash algorithm has been performed. 2179 2180 @type salt: L{Charset} 2181 @ivar salt: Identifies the salt value provided to the hash. 2182 2183 @type nxt_hash_owner_name: L{Charset} 2184 @ivar nxt_hash_owner_name: Contains the next hashed owner name in the zone in hash order. 2185 2186 @type type_bitmaps: L{TypeBitmaps} 2187 @ivar type_bitmaps: Identifies the RRset types that exist at the NSEC3 RR's original owner name. 2188 2189 @type ttl: C{int} 2190 @ivar ttl: The maximum number of seconds which this record should be 2191 cached. 2192 """ 2193 implements(IEncodable, IRecord) 2194 TYPE = NSEC3 2195 fmt = '!BBH' 2196 2197 fancybasename = 'NSEC3' 2198 showAttributes = ('hash_algo', 'flags', 'iterations', ('_salt', 'salt', '%s'), ('nxt_hash_owner_name', 'nxt_hash_owner_name', '%s'), ('_type_bitmaps', 'type_bitmaps', '%s'), 'ttl') 2199 compareAttributes = ('hash_algo', 'flags', 'iterations', 'salt', 'nxt_hash_owner_name', 'type_bitmaps', 'ttl') 2200 2201 _salt = property(lambda self: self.salt.string) 2202 _type_bitmaps = property(lambda self: self.type_bitmaps.string) 2203 2204 def __init__(self, hash_algo=0, flags=0, iterations=0, salt='', nxt_hash_owner='', type_bitmaps=None, ttl=None): 2205 Record_NSEC3PARAM.__init__( self, hash_algo, flags, iterations, salt, ttl) 2206 self.nxt_hash_owner_name = Charstr(nxt_hash_owner) 2207 self.type_bitmaps = TypeBitmaps(type_bitmaps) 2208 2209 def encode(self, strio, compDict = None): 2210 Record_NSEC3PARAM.encode(self, strio, compDict) 2211 self.nxt_hash_owner_name.encode(strio, None) 2212 self.type_bitmaps.encode(strio, None) 2213 2214 def decode(self, strio, length=None): 2215 start = strio.tell() 2216 Record_NSEC3PARAM.decode(self, strio, compDict) 2217 self.nxt_hash_owner_name.decode(strio) 2218 here = strio.tell() 2219 self.type_bitmaps.decode(strio, length + start - here if length else None) 2220 2221 def __hash__(self): 2222 return hash((self.hash_algo, self.flags, self.iterations, self.salt, 2223 self.nxt_hash_owner_name, self.type_bitmaps)) 2224 1473 2225 # This is a fallback record 1474 2226 class UnknownRecord(tputil.FancyEqMixin, tputil.FancyStrMixin, object): 1475 2227 """ … … 1546 2298 queries = answers = add = ns = None 1547 2299 1548 2300 def __init__(self, id=0, answer=0, opCode=0, recDes=0, recAv=0, 1549 auth=0, rCode=OK, trunc=0, maxSize=512):2301 auth=0, rCode=OK, trunc=0, maxSize=512, authData=0, chkDis=0): 1550 2302 self.maxSize = maxSize 1551 2303 self.id = id 1552 2304 self.answer = answer 1553 2305 self.opCode = opCode 1554 self.auth = auth 1555 self.trunc = trunc 1556 self.recDes = recDes 1557 self.recAv = recAv 2306 self.auth = auth #AA - Authoritative Answer 2307 self.trunc = trunc #TC - TrunCated 2308 self.recDes = recDes #RD - Recursion Desired 2309 self.recAv = recAv #RA - Recursion Available 2310 self.authData = authData #AD - Authentic Data 2311 self.chkDis = chkDis #CD - Checking Disabled 1558 2312 self.rCode = rCode 1559 2313 self.queries = [] 1560 2314 self.answers = [] … … 1599 2353 | ((self.auth & 1 ) << 2 ) 1600 2354 | ((self.trunc & 1 ) << 1 ) 1601 2355 | ( self.recDes & 1 ) ) 1602 byte4 = ( ( (self.recAv & 1 ) << 7 ) 2356 byte4 = ( ((self.recAv & 1 ) << 7 ) 2357 |((self.authData & 1 ) << 5 ) 2358 |((self.chkDis & 1 ) << 4 ) 1603 2359 | (self.rCode & 0xf ) ) 1604 2360 1605 2361 strio.write(struct.pack(self.headerFmt, self.id, byte3, byte4, … … 1619 2375 self.trunc = ( byte3 >> 1 ) & 1 1620 2376 self.recDes = byte3 & 1 1621 2377 self.recAv = ( byte4 >> 7 ) & 1 2378 self.authData = ( byte4 >> 5 ) & 1 2379 self.chkDis = ( byte4 >> 4 ) & 1 1622 2380 self.rCode = byte4 & 0xf 1623 2381 1624 2382 self.queries = [] … … 1637 2395 1638 2396 def parseRecords(self, list, num, strio): 1639 2397 for i in range(num): 1640 header = RRHeader(auth=self.auth)1641 2398 try: 1642 header .decode(strio)2399 header = OPTHeader.factory(strio, auth=self.auth) 1643 2400 except EOFError: 1644 2401 return 1645 2402 t = self.lookupRecordType(header.type) -
names/test/test_dns.py
8 8 9 9 from cStringIO import StringIO 10 10 11 import re 11 12 import struct 12 13 13 14 from twisted.python.failure import Failure 14 15 from twisted.internet import address, task 15 16 from twisted.internet.error import CannotListenError, ConnectionDone 16 17 from twisted.trial import unittest 17 from twisted.names import dns 18 from twisted.names import dns, common 18 19 19 20 from twisted.test import proto_helpers 20 21 … … 25 26 dns.Record_WKS, dns.Record_SRV, dns.Record_AFSDB, dns.Record_RP, 26 27 dns.Record_HINFO, dns.Record_MINFO, dns.Record_MX, dns.Record_TXT, 27 28 dns.Record_AAAA, dns.Record_A6, dns.Record_NAPTR, dns.UnknownRecord, 29 dns.Record_OPT, dns.Record_RRSIG, dns.Record_DS, dns.Record_DNSKEY, 30 dns.Record_NSEC, dns.Record_NSEC3PARAM, dns.Record_NSEC3, 28 31 ] 29 32 30 33 class NameTests(unittest.TestCase): … … 189 192 """Encoding and then decoding various objects.""" 190 193 191 194 names = ["example.org", "go-away.fish.tv", "23strikesback.net"] 192 195 sigs = ["Qm12VZVaZgKS0/DZx35SGECDwPiTTf3ngChb7OkgSv5iupVmJGhPWudm /18qBSXKyv9hxMlEXFFgpBieNqLfSBkP1bwKnlqPfr1Hx7ctDwDUpkT3 cS8u/ms9yo3Fu1ybpO4Hfsb1HbA2N3zzQnjWKnyk26AAQSz8KgjNTFzD tJM=", 196 "ZH2kahMD1g2WOieIotAcBwB0e/o30Zq6YR//M/xwP1ktkYuclmcR56iv XiR3QFWqmN5Xz3YpgmM4tZkjIeSMp2doYa7XYORZ7OpzG7oyfo8IoXxc j1VGDeAn1CeNCpBtoSGapRABG1gjY7oeRj/smPQPp2Gkf79+WZfuzRom /t4=", 197 "AZpaboyNQAmbnBO1K66QmZ0c+VCdY/wu9QpEdRnMpnIOLPD28pNVu6hk GQMz6eg5WYkPYDdJK+1D/oyAQkDmRgn10+O9EdeFDyLqYqq/htEAvDm4 CziMSOpD/mkg1bSWCZ2mdln/GBk8WooCeeM7LEHmRjmHMMj0xb6N4SKa MEc=", 198 "AwEAAbi5VQa3x+R3WQouBDNts+ZX2zIKZNoj9pzl7ew446kI/2omv3j6 c/4RQ6VneYE3mK7r0fFIKhVagmiRroFO1rRUJ8sVidssZ35CldE0sju+ E7wymVg3tV+ZUUO/+5v6Sfj+tw3rlp6eKqm7EGKKM88t+KuXiGYMu0Vw Rm9OUO1n", 199 "AwEAAbmTL+kuV45kAxGN//iBKz93Y6lutgxoptp+I1+PZZMsBkhm/dZj q57040Pz/Hr3f2zQX7z6fFu7/Ml3MHPH1eQDiVXDvOkeNq2x4IbCO7x+ 0p6bGYj4fw/tEfh/8dUzyzvMwfuAMsOvXza8Kh+UP4jvFc95cUuGgYus uEjUOp40PsL7EtYvAks3UssA6/OZP4w/1Z5m/VFx4PzgY0dkEuc=", 200 "VGPxa8A81eV1dtUxVhz9b9Jsp6FF4M5H6J0QhzbNCUTHTHjLNR2VHYfE fM+Akwo3/qKq3D6vzTfzqtyPAXP8CmGfdD8hfv0s7Hae9c7Is8usdlrk ZpoXEFMW+YVG8G9OieYViq6tBIpUvKgMVZ+oXKo63KJ/tC/yBW0H0VQP YwdzZ3ZvYRDmZDvrXoX7T0YNU+0HYHnb7g7nUECIJ/4HHg==", 201 "M+u8Uxm2y2Q142qED0kVNIiSOHBkfiU3xBhMq9H4T/K+oeC7Y81HIOFE h9k6ZS/Ba5X0/Fr1yyq5Z/+0/Q845Kya8Lmkp/ikJVe/9id2TC2hoffp Z9pbZRjIeBTAvdTboGmGuqG/ljnDLJrJpoF6g8g6fHR9eekIWis8LJ55 Y1k="] 202 type_bitmaps = ["A MX RRSIG NSEC TYPE1234", 203 "AAAA NS CNAME MX TXT RRSIG NSEC3 DNAME", 204 "NSEC3 A AAAA RRSIG DS NS TYPE5000 TYPE1000 TYPE2000 TYPE3000 TYPE4000", 205 None] 206 193 207 def testName(self): 194 208 for n in self.names: 195 209 # encode the name … … 276 290 self.assertEqual(result.string, n) 277 291 278 292 293 def test_Sigstr(self): 294 """ 295 Test L{dns.Sigstr} encode and decode. 296 """ 297 for s in self.sigs: 298 # encode the signature/key 299 f = StringIO() 300 dns.Sigstr(s).encode(f) 301 l = f.tell() 302 303 # decode the signature/key 304 f.seek(0, 0) 305 result = dns.Sigstr() 306 result.decode(f,l) 307 #spaces are free, and dig sticks them in 308 self.assertEqual(result.string, s.replace(' ', '')) 309 310 311 def test_TypeBitmaps(self): 312 """ 313 Test L{dns.TypeBitmaps} encode and decode. 314 """ 315 typeRegex = re.compile('TYPE(\d+)') 316 317 for b in self.type_bitmaps: 318 # encode the type_bitmaps 319 f = StringIO() 320 dns.TypeBitmaps(b).encode(f) 321 l = f.tell() 322 323 # decode the type_bitmaps 324 f.seek(0, 0) 325 result = dns.TypeBitmaps() 326 result.decode(f,l) 327 328 def mnuVal(mnu): 329 mnuVal = dns.REV_TYPES.get(mnu, None) 330 if not mnuVal: 331 m = typeRegex.match(mnu) 332 if m.groups(): 333 mnuVal = int(m.group(1)) 334 assert mnuVal < 65536 335 else: 336 log.err("can't parse %s in %s" % (mnu, self.string, )) 337 mnuVal = 0 338 return mnuVal 339 340 def sorttok(string): 341 if not string: 342 return '' 343 344 toks = string.split(' ') 345 toks.sort(key = mnuVal) 346 return ' '.join(toks) 347 348 self.assertEqual(result.type_bitmaps, sorttok(b)) 349 350 279 351 def test_NAPTR(self): 280 352 """ 281 353 Test L{dns.Record_NAPTR} encode and decode. … … 439 511 Initialize the controller: create a list of messages. 440 512 """ 441 513 self.messages = [] 514 self.dnssecConfig = common.DnssecConfig() 442 515 443 516 444 517 def messageReceived(self, msg, proto, addr): … … 893 966 repr(dns.UnknownRecord("foo\x1fbar", 12)), 894 967 "<UNKNOWN data='foo\\x1fbar' ttl=12>") 895 968 969 def test_dnskey(self): 970 """ 971 The repr of a L{dns.DNSKEY} instance includes the flags, protocol, 972 algo, pub_key and ttl fields of the record. 973 """ 974 self.assertEqual( 975 repr(dns.Record_DNSKEY(10, 20, 30, "foo\x1fbar", ttl=20)), 976 "<DNSKEY flags=10 protocol=20 algo=30 pub_key=foo\x1fbar ttl=20>") 977 978 def test_ds(self): 979 """ 980 The repr of a L{dns.DS} instance includes the key_tag, algo, digest_type, 981 digest and ttl fields of the record. 982 """ 983 self.assertEqual( 984 repr(dns.Record_DS(11, 22, 33, "foo\x1fbar1", ttl=21)), 985 "<DS key_tag=11 algo=22 digest_type=33 digest=foo\x1fbar1 ttl=21>") 986 987 def test_nsec(self): 988 """ 989 The repr of a L{dns.NSEC} instance includes the nxt_name, type_bitmaps and 990 ttl fields of the record. 991 """ 992 self.assertEqual( 993 repr(dns.Record_NSEC('bob', "\x1fabcd", ttl=31)), 994 "<NSEC nxt_name=bob type_bitmaps=\x1fabcd ttl=31>") 995 996 def test_nsec3param(self): 997 """ 998 The repr of a L{dns.NSEC3PARAM} instance includes the hash_algo, flags, 999 iterations, salt and ttl fields of the record. 1000 """ 1001 self.assertEqual( 1002 repr(dns.Record_NSEC3PARAM(1, 2, 3, '\x12\x34', ttl=31)), 1003 "<NSEC3 hash_algo=1 flags=2 iterations=3 salt=\x12\x34 ttl=31>") 1004 1005 def test_nsec3(self): 1006 """ 1007 The repr of a L{dns.NSEC3} instance includes the hash_algo, flags, iterations, 1008 salt, nxt_hash_owner_name, type_bitmaps and ttl fields of the record. 1009 """ 1010 self.assertEqual( 1011 repr(dns.Record_NSEC3(1, 2, 3, '\x12\x34', 'bob', "\x1fabcd", ttl=31)), 1012 "<NSEC3 hash_algo=1 flags=2 iterations=3 salt=\x12\x34 nxt_hash_owner_name=bob type_bitmaps=\x1fabcd ttl=31>") 1013 1014 def test_opt(self): 1015 """ 1016 The repr of a L{dns.OPT} instance includes the payload_size, dnssecOk flag, 1017 and version fields of the record. (The OPT record has no ttl field.) 1018 """ 1019 self.assertEqual( 1020 repr(dns.Record_OPT(payload_size=1492, dnssecOk=1, version=0)), 1021 "<OPT payload_size=1492 flags=0x8000 version=0>") 896 1022 1023 def test_rrsig(self): 1024 """ 1025 The repr of a L{dns.RRSIG} instance includes the algo, labels, original_ttl 1026 sig_expiration, sig_inception, key_tag, signers_name, signature and ttl 1027 fields of the record. 1028 """ 1029 self.assertEqual( 1030 repr(dns.Record_RRSIG(type_covered=dns.A, 1031 algo=2, 1032 labels=3, 1033 original_ttl=30, 1034 sig_expiration='20110101123456', 1035 sig_inception= '20110202112233', 1036 key_tag=60, 1037 signers_name='bob', 1038 signature='\x12\x34sig', 1039 ttl=70)), 1040 "<RRSIG type_covered=1 algo=2 labels=3 original_ttl=30" 1041 + " sig_expiration=20110101123456 sig_inception=20110202112233 key_tag=60" 1042 + " signers_name=bob signature=\x12\x34sig ttl=70>") 897 1043 898 1044 class _Equal(object): 899 1045 """ … … 961 1107 cls('example.com', 123), 962 1108 cls('example.org', 123)) 963 1109 1110 def test_optheader(self): 1111 """ 1112 Two OptHeader instances comapare equal iff the have the same 1113 (Record_OPT) payload and auth bit. 1114 """ 1115 self._equalityTest( 1116 dns.OPTHeader(payload=dns.Record_OPT(payload_size=1024, dnssecOk=True, version=0, ttl=30)), 1117 dns.OPTHeader(payload=dns.Record_OPT(payload_size=1024, dnssecOk=True, version=0, ttl=30)), 1118 dns.OPTHeader(payload=dns.Record_OPT(payload_size=1492, dnssecOk=False, version=0, ttl=40), auth=True)) 964 1119 965 1120 def test_rrheader(self): 966 1121 """ … … 1483 1638 dns.UnknownRecord('foo', ttl=10), 1484 1639 dns.UnknownRecord('foo', ttl=10), 1485 1640 dns.UnknownRecord('foo', ttl=100)) 1641 1642 def test_rrsig(self): 1643 """ 1644 L(dns.RRSIG) instances compare equal iff they have the same 1645 type_covered, algo, labels, original_ttl, sig_expiration, sig_inception, 1646 key_tag, signers_name, signature, and ttl 1647 """ 1648 self._equalityTest( 1649 dns.Record_RRSIG(type_covered=dns.A), 1650 dns.Record_RRSIG(type_covered=dns.A), 1651 dns.Record_RRSIG(type_covered=dns.AAAA)) 1652 self._equalityTest( 1653 dns.Record_RRSIG(algo=1), 1654 dns.Record_RRSIG(algo=1), 1655 dns.Record_RRSIG(algo=2)) 1656 self._equalityTest( 1657 dns.Record_RRSIG(labels=3), 1658 dns.Record_RRSIG(labels=3), 1659 dns.Record_RRSIG(labels=4)) 1660 self._equalityTest( 1661 dns.Record_RRSIG(original_ttl=5), 1662 dns.Record_RRSIG(original_ttl=5), 1663 dns.Record_RRSIG(original_ttl=6)) 1664 self._equalityTest( 1665 dns.Record_RRSIG(sig_expiration='20110101000000'), 1666 dns.Record_RRSIG(sig_expiration='20110101000000'), 1667 dns.Record_RRSIG(sig_expiration='20110101000001')) 1668 self._equalityTest( 1669 dns.Record_RRSIG(sig_inception='20120101000000'), 1670 dns.Record_RRSIG(sig_inception='20120101000000'), 1671 dns.Record_RRSIG(sig_inception='20120101000001')) 1672 self._equalityTest( 1673 dns.Record_RRSIG(key_tag=11), 1674 dns.Record_RRSIG(key_tag=11), 1675 dns.Record_RRSIG(key_tag=12)) 1676 self._equalityTest( 1677 dns.Record_RRSIG(signers_name='bob'), 1678 dns.Record_RRSIG(signers_name='bob'), 1679 dns.Record_RRSIG(signers_name='joe')) 1680 self._equalityTest( 1681 dns.Record_RRSIG(signature='abcdef'), 1682 dns.Record_RRSIG(signature='abcdef'), 1683 dns.Record_RRSIG(signature='abcdefg')) 1684 self._equalityTest( 1685 dns.Record_RRSIG(ttl=10), 1686 dns.Record_RRSIG(ttl=10), 1687 dns.Record_RRSIG(ttl=20)) 1688 1689 def test_ds(self): 1690 """ 1691 L(dns.DS) instances compare equal iff they have the same 1692 key_tag, algo, digest_type, digest and ttl 1693 """ 1694 self._equalityTest( 1695 dns.Record_DS(key_tag=1), 1696 dns.Record_DS(key_tag=1), 1697 dns.Record_DS(key_tag=2)) 1698 self._equalityTest( 1699 dns.Record_DS(algo=3), 1700 dns.Record_DS(algo=3), 1701 dns.Record_DS(algo=4)) 1702 self._equalityTest( 1703 dns.Record_DS(digest_type=5), 1704 dns.Record_DS(digest_type=5), 1705 dns.Record_DS(digest_type=6)) 1706 self._equalityTest( 1707 dns.Record_DS(digest='abcdef-digest'), 1708 dns.Record_DS(digest='abcdef-digest'), 1709 dns.Record_DS(digest='abcdef-digest-f')) 1710 self._equalityTest( 1711 dns.Record_DS(ttl=10), 1712 dns.Record_DS(ttl=10), 1713 dns.Record_DS(ttl=20)) 1714 1715 def test_dnskey(self): 1716 """ 1717 L(dns.DNSKEY) instances compare equal iff they have the same 1718 flags, protocol, algo, pub_key and ttl 1719 """ 1720 self._equalityTest( 1721 dns.Record_DNSKEY(flags=1), 1722 dns.Record_DNSKEY(flags=1), 1723 dns.Record_DNSKEY(flags=2)) 1724 self._equalityTest( 1725 dns.Record_DNSKEY(protocol=3), 1726 dns.Record_DNSKEY(protocol=3), 1727 dns.Record_DNSKEY(protocol=4)) 1728 self._equalityTest( 1729 dns.Record_DNSKEY(algo=5), 1730 dns.Record_DNSKEY(algo=5), 1731 dns.Record_DNSKEY(algo=6)) 1732 self._equalityTest( 1733 dns.Record_DNSKEY(pub_key='abcdef-digest'), 1734 dns.Record_DNSKEY(pub_key='abcdef-digest'), 1735 dns.Record_DNSKEY(pub_key='abcdef-digest-f')) 1736 self._equalityTest( 1737 dns.Record_DNSKEY(ttl=10), 1738 dns.Record_DNSKEY(ttl=10), 1739 dns.Record_DNSKEY(ttl=20)) 1740 1741 def test_nsec(self): 1742 """ 1743 L(dns.DNSKEY) instances compare equal iff they have the same 1744 nxt_name, type_bitmaps and ttl 1745 """ 1746 self._equalityTest( 1747 dns.Record_NSEC(nxt_name="example.com"), 1748 dns.Record_NSEC(nxt_name="example.com"), 1749 dns.Record_NSEC(nxt_name="a.example.com")) 1750 self._equalityTest( 1751 dns.Record_NSEC(type_bitmaps="A AAAA NS NSEC3"), 1752 dns.Record_NSEC(type_bitmaps="A AAAA NS NSEC3"), 1753 dns.Record_NSEC(type_bitmaps="A AAAA NS NSEC3 RRSIG")) 1754 self._equalityTest( 1755 dns.Record_NSEC(ttl=5), 1756 dns.Record_NSEC(ttl=5), 1757 dns.Record_NSEC(ttl=6)) 1758 1759 def test_nsec3param(self): 1760 """ 1761 L(dns.DNSKEY) instances compare equal iff they have the same 1762 hash_algo, flags, iterations, salt, nxt_hash_owner_name, type_bitmaps and ttl 1763 """ 1764 self._equalityTest( 1765 dns.Record_NSEC3PARAM(hash_algo=1), 1766 dns.Record_NSEC3PARAM(hash_algo=1), 1767 dns.Record_NSEC3PARAM(hash_algo=2)) 1768 self._equalityTest( 1769 dns.Record_NSEC3PARAM(flags=1), 1770 dns.Record_NSEC3PARAM(flags=1), 1771 dns.Record_NSEC3PARAM(flags=2)) 1772 self._equalityTest( 1773 dns.Record_NSEC3PARAM(iterations=5), 1774 dns.Record_NSEC3PARAM(iterations=5), 1775 dns.Record_NSEC3PARAM(iterations=6)) 1776 self._equalityTest( 1777 dns.Record_NSEC3PARAM(salt="abcdef"), 1778 dns.Record_NSEC3PARAM(salt="abcdef"), 1779 dns.Record_NSEC3PARAM(salt="abcdefg")) 1780 self._equalityTest( 1781 dns.Record_NSEC3PARAM(ttl=5), 1782 dns.Record_NSEC3PARAM(ttl=5), 1783 dns.Record_NSEC3PARAM(ttl=6)) 1784 1785 def test_nsec3(self): 1786 """ 1787 L(dns.DNSKEY) instances compare equal iff they have the same 1788 hash_algo, flags, iterations, salt, nxt_hash_owner_name, type_bitmaps and ttl 1789 """ 1790 self._equalityTest( 1791 dns.Record_NSEC3(hash_algo=1), 1792 dns.Record_NSEC3(hash_algo=1), 1793 dns.Record_NSEC3(hash_algo=2)) 1794 self._equalityTest( 1795 dns.Record_NSEC3(flags=1), 1796 dns.Record_NSEC3(flags=1), 1797 dns.Record_NSEC3(flags=2)) 1798 self._equalityTest( 1799 dns.Record_NSEC3(iterations=5), 1800 dns.Record_NSEC3(iterations=5), 1801 dns.Record_NSEC3(iterations=6)) 1802 self._equalityTest( 1803 dns.Record_NSEC3(salt="abcdef"), 1804 dns.Record_NSEC3(salt="abcdef"), 1805 dns.Record_NSEC3(salt="abcdefg")) 1806 self._equalityTest( 1807 dns.Record_NSEC3(nxt_hash_owner="example.com"), 1808 dns.Record_NSEC3(nxt_hash_owner="example.com"), 1809 dns.Record_NSEC3(nxt_hash_owner="a.example.com")) 1810 self._equalityTest( 1811 dns.Record_NSEC3(type_bitmaps="A AAAA NS NSEC3"), 1812 dns.Record_NSEC3(type_bitmaps="A AAAA NS NSEC3"), 1813 dns.Record_NSEC3(type_bitmaps="A AAAA NS NSEC3 RRSIG")) 1814 self._equalityTest( 1815 dns.Record_NSEC3(ttl=5), 1816 dns.Record_NSEC3(ttl=5), 1817 dns.Record_NSEC3(ttl=6)) 1818 1819 1820 1821 No newline at end of file
