Ticket #5453: add-edn0-dnssec-record-types-01.patch
File add-edn0-dnssec-record-types-01.patch, 53.6 KB (added by , 6 years ago) |
---|
-
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.serialNumberArithmetic 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): 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() 726 rrh.decode(strio) 727 return rrh 728 729 __repr__ = __str__ 730 731 732 class RRHeader(OPTHeader): 733 """ 439 734 A resource record header. 440 735 441 736 @cvar fmt: C{str} specifying the byte format of an RR. … … 1467 1762 return hash(tuple(self.data)) 1468 1763 1469 1764 1765 class Record_OPT(tputil.FancyEqMixin, tputil.FancyStrMixin): 1766 """ 1767 EDNS0 Option record. 1768 1769 @type payload_size: C{int} 1770 @ivar payload_size: Specifies the max UDP Packet size (bytes) that your 1771 network can handle. 1772 1773 @type dnssecOk: C{bool} 1774 @ivar dnssecOk: Requests the server to send DNSSEC RRs and to do DNSSEC 1775 validation (and set the AD bit if the response validates). 1776 1777 @type version: C{int} 1778 @ivar version: The version of DNSSEC used. Currently only version 0 1779 is defined. 1780 """ 1781 implements(IEncodable, IRecord) 1782 TYPE = OPT 1783 fmt = '!HBBHH' 1784 1785 fancybasename = 'OPT' 1786 showAttributes = ('payload_size', ('flags', 'flags', '0x%x'), 'version') 1787 compareAttributes = ('payload_size', 'flags', 'version') 1788 1789 def __init__(self, payload_size=512, dnssecOk=0, version=0, ttl=None): 1790 self.payload_size = payload_size 1791 self.version = version 1792 self.flags = (dnssecOk & 1) << 15 1793 1794 def encode(self, strio, compDict = None): 1795 OPTHeader().encode(strio) 1796 strio.write(struct.pack('!H', self.payload_size)) 1797 strio.write(struct.pack('!B', 0)) # high order 0 1798 strio.write(struct.pack('!B', self.version)) 1799 strio.write(struct.pack('!H', self.flags)) # DO(bit) + Z's 1800 strio.write(struct.pack('!H', 0)) # Data length: 0 1801 1802 def decode(self, strio, length=None): 1803 ''' 1804 are OPT Records always 0 rdlength? 1805 ''' 1806 l = struct.calcsize(self.fmt) 1807 buff = readPrecisely(strio, l) 1808 r = struct.unpack(self.fmt, buff) 1809 self.payload_size, z, self.version, self.flags, length = r 1810 assert length == 0 1811 1812 def __hash__(self): 1813 return hash((self.payload_size, self.version, self.flags)) 1470 1814 1815 class Record_RRSIG(tputil.FancyEqMixin, tputil.FancyStrMixin): 1816 """ 1817 DNSSEC RRSIG record. See RFC 4034 for details. 1818 1819 @type type_covered: C{int} 1820 @ivar type_covered: Identifies the type of the RRset that this RRSIG covers. 1821 1822 @type algo: C{int} 1823 @ivar algo: Identifies the crypto algorithm type used to create the signature. 1824 (5 - RSH/SHA-1 is mandatory. See RFC 4034 App A.1 for the full list.) 1825 1826 @type labels: C{int} 1827 @ivar labels: Specifies the number of labels in the original RRSIG RR owner name. 1828 A validator can use this to determine whether the answer was synthesized from 1829 a wildcard. 1830 1831 @type original_ttl: C{int} 1832 @ivar original_ttl: Specifies the TTL of the covered RRset as it appears in the 1833 authoritative zone. 1834 1835 @type sig_expiration: C{int} 1836 @ivar sig_expiration: This RRSIG must NOT be used after this time. Seconds 1837 since 1/1/1970, Modulo 2**32, compare using DNS Serial Number Arithmetic 1838 1839 @type sig_inception: C{int} 1840 @ivar sig_inception: This RRSIG must NOT be used prior to this time. Seconds 1841 since 1/1/1970, Modulo 2**32, compare using DNS Serial Number Arithmetic 1842 1843 @type key_tag: C{int} 1844 @ivar key_tag: Contains the key tag value of the DNSKEY RR that validates this 1845 signature, in network byte order. See RFC 4034 App B. 1846 1847 @type signers_name: L{Name} 1848 @ivar signers_name: Identifies the owner name of the DNSKEY RR that a validator 1849 should use to validate this signature. Must not use DNS name compression. 1850 1851 @type signature: L{Sigstr} 1852 @ivar signature: Contains the cryptographic signature that covers the RRSIG 1853 RDATA (excluding the Signature field and the RRset specified by the RRSIG 1854 owner name, RRSIG class and RRSIG Type Covered fields. 1855 1856 @type ttl: C{int} 1857 @ivar ttl: The maximum number of seconds which this record should be 1858 cached. 1859 """ 1860 implements(IEncodable, IRecord) 1861 TYPE = RRSIG 1862 fmt = '!HBBIIIH' 1863 1864 fancybasename = 'RRSIG' 1865 showAttributes = ('type_covered', 'algo', 'labels', 'original_ttl', 1866 ('_sig_expiration', 'sig_expiration', '%s'), 1867 ('_sig_inception', 'sig_inception', '%s'), 1868 'key_tag', 1869 ('signers_name', 'signers_name', '%s'), 1870 ('_signature', 'signature', '%s'), 'ttl') 1871 compareAttributes = ('type_covered', 'algo', 'labels', 'original_ttl', 1872 'sig_expiration', 'sig_inception', 'key_tag', 1873 'signers_name', 'signature', 'ttl') 1874 1875 _sig_expiration = property(lambda self: str(self.sig_expiration)) 1876 _sig_inception = property(lambda self: str(self.sig_inception)) 1877 _signature = property(lambda self: self.signature.string) 1878 1879 def __init__(self, type_covered=A, algo=0, labels=0, original_ttl=0, 1880 sig_expiration='', sig_inception='', key_tag=0, 1881 signers_name='', signature='', ttl=None): 1882 self.type_covered = type_covered 1883 self.algo = algo 1884 self.labels = labels 1885 self.original_ttl = original_ttl 1886 self.sig_expiration = DateSNA(sig_expiration) 1887 self.sig_inception = DateSNA(sig_inception) 1888 self.key_tag = key_tag 1889 self.signers_name = Name(signers_name) 1890 self.signature = Sigstr(signature) 1891 self.ttl = str2time(ttl) 1892 1893 def encode(self, strio, compDict = None): 1894 strio.write(struct.pack(self.fmt, 1895 self.type_covered, 1896 self.algo, 1897 self.labels, 1898 self.original_ttl, 1899 self.sig_expiration.asInt(), 1900 self.sig_inception.asInt(), 1901 self.key_tag)) 1902 self.signers_name.encode(strio, None) 1903 self.signature.encode(strio, compDict) 1904 1905 def decode(self, strio, length=None): 1906 start = strio.tell() 1907 l = struct.calcsize(self.fmt) 1908 buff = readPrecisely(strio, l) 1909 r = struct.unpack(self.fmt, buff) 1910 self.type_covered, self.algo, self.labels, self.original_ttl, \ 1911 sig_expiration, sig_inception, self.key_tag = r 1912 self.sig_expiration = DateSNA.fromInt(sig_expiration) 1913 self.sig_inception = DateSNA.fromInt(sig_inception) 1914 self.signers_name.decode(strio) 1915 here = strio.tell() 1916 self.signature.decode(strio, length + start - here if length else None) 1917 1918 def __hash__(self): 1919 return hash((self.type_covered, self.algo, self.labels, self.original_ttl, 1920 self.sig_expiration, self.sig_inception, self.key_tag, 1921 self.signers_name, self.signature)) 1922 1923 class Record_DS(tputil.FancyEqMixin, tputil.FancyStrMixin): 1924 """ 1925 A DNSSEC DS record. 1926 1927 @type key_tag: C{int} 1928 @ivar key_tag: Lists the key tag of the DNSKEY RR referred to by this DS record. 1929 1930 @type algo: C{int} 1931 @ivar algo: Lists the algorithm number of the DNSKEY RR referenced by this DS record. 1932 1933 @type digest_type: C{int} 1934 @ivar digest_type: Identifies the algorithm used to construct the digest field. 1935 1936 @type digest: L{Sigstr} 1937 @ivar digest: Contains a digest of the refeerenced DNSKEY RR calculated by the 1938 algorithm identified by the digest_type field. 1939 1940 @type ttl: C{int} 1941 @ivar ttl: The maximum number of seconds which this record should be 1942 cached. 1943 """ 1944 implements(IEncodable, IRecord) 1945 TYPE = DS 1946 fmt = '!HBB' 1947 1948 fancybasename = 'DS' 1949 showAttributes = ('key_tag', 'algo', 'digest_type', ('_digest', 'digest', '%s'), 'ttl') 1950 compareAttributes = ('key_tag', 'algo', 'digest_type', 'digest', 'ttl') 1951 1952 _digest = property(lambda self: self.digest.string) 1953 1954 def __init__(self, key_tag=0, algo=0, digest_type=0, digest='', ttl=None): 1955 self.key_tag = key_tag 1956 self.algo = algo 1957 self.digest_type = digest_type 1958 self.digest = Sigstr(digest) 1959 self.ttl = str2time(ttl) 1960 1961 def encode(self, strio, compDict = None): 1962 strio.write(struct.pack(self.fmt, 1963 self.key_tag, 1964 self.algo, 1965 self.digest_type)) 1966 self.digest.encode(strio, None) 1967 1968 def decode(self, strio, length=None): 1969 start = strio.tell() 1970 l = struct.calcsize(self.fmt) 1971 buff = readPrecisely(strio, l) 1972 r = struct.unpack(self.fmt, buff) 1973 self.key_tag, self.algo, self.digest_type = r 1974 here = strio.tell() 1975 self.digest.decode(strio, length + start - here if length else None) 1976 1977 def __hash__(self): 1978 return hash((self.key_tag, self.algo, self.digest_type, self.digest)) 1979 1980 class Record_DNSKEY(tputil.FancyEqMixin, tputil.FancyStrMixin): 1981 """ 1982 A DNSSEC DNSKEY record. Holds the public key for a signed RRset. 1983 1984 @type flags: C{int} 1985 @ivar flags: Bit 7 is the Zone Key flag. If bit 7 has value 1, then the 1986 DNSKEY record holds a DNS zone key and the DNSKEY RR's owner name is 1987 the name of a zone. If bit 7 has value 0, then the DNSKEY record 1988 holds some other type of DNS public key and MUST NOT be used to 1989 verify RRSIGs that cover RRsets. 1990 Bit 15 is the Secure Entry Point flag. See RFC 3757.) 1991 All other bits are reserved and must be zero. 1992 1993 @type protocol: C{int} 1994 @ivar protocol: Must have value 3. The DNSKEY RR must be treated as invalid 1995 if this field does not contain 3. 1996 1997 @type algo: C{int} 1998 @ivar algo: Identifies the public key's cryptographic algorithm and determines 1999 the format of the pub_key field. See RFC 4034 App A. 2000 2001 @type pub_key: L{Sigstr} 2002 @ivar pub_key: Holds the public key material. 2003 2004 @type ttl: C{int} 2005 @ivar ttl: The maximum number of seconds which this record should be 2006 cached. 2007 """ 2008 implements(IEncodable, IRecord) 2009 TYPE = DNSKEY 2010 fmt = '!HBB' 2011 2012 fancybasename = 'DNSKEY' 2013 showAttributes = ('flags', 'protocol', 'algo', ('_pub_key', 'pub_key', '%s'), 'ttl') 2014 compareAttributes = ('flags', 'protocol', 'algo', 'pub_key', 'ttl') 2015 2016 _pub_key = property(lambda self: self.pub_key.string) 2017 2018 def __init__(self, flags=0, protocol=0, algo=0, pub_key='', ttl=None): 2019 self.flags = flags 2020 self.protocol = protocol 2021 self.algo = algo 2022 self.pub_key = Sigstr(pub_key) 2023 self.ttl = str2time(ttl) 2024 2025 def encode(self, strio, compDict = None): 2026 strio.write(struct.pack(self.fmt, 2027 self.flags, 2028 self.protocol, 2029 self.algo)) 2030 self.pub_key.encode(strio, None) 2031 2032 def decode(self, strio, length=None): 2033 start = strio.tell() 2034 l = struct.calcsize(self.fmt) 2035 buff = readPrecisely(strio, l) 2036 r = struct.unpack(self.fmt, buff) 2037 self.flags, self.protocol, self.algo = r 2038 here = strio.tell() 2039 self.pub_key.decode(strio, length + start - here if length else None) 2040 2041 def __hash__(self): 2042 return hash((self.flags, self.protocol, self.algo, self.pub_key)) 2043 2044 class Record_NSEC(tputil.FancyEqMixin, tputil.FancyStrMixin): 2045 """ 2046 A DNSSEC NSEC record provides authenticated denial of existance for DNS data. 2047 2048 A DNSSEC NSEC record lists: 2049 2050 1) the next owner name in canonical ordering of the zone that contains authoritataive 2051 data or a delegation point NS RRset. 2052 2053 2) the set of RR types present at the NSEC RR's owner name. 2054 2055 @type nxt_name: L{Name} 2056 @ivar nxt_name: The next owner name that has authoritative data or contains a 2057 delegation point NS RRset. 2058 2059 @type type_bitmaps: L{TypeBitmaps} 2060 @ivar type_bitmaps: Identifies the RRset types that exist at the NSEC RR's owner name. 2061 2062 @type ttl: C{int} 2063 @ivar ttl: The maximum number of seconds which this record should be 2064 cached. 2065 """ 2066 implements(IEncodable, IRecord) 2067 TYPE = NSEC 2068 2069 fancybasename = 'NSEC' 2070 showAttributes = (('nxt_name', 'nxt_name', '%s'), ('_type_bitmaps', 'type_bitmaps', '%s'), 'ttl') 2071 compareAttributes = ('nxt_name', 'type_bitmaps', 'ttl') 2072 2073 _type_bitmaps = property(lambda self: self.type_bitmaps.string) 2074 2075 def __init__(self, nxt_name='', type_bitmaps=None, ttl=None): 2076 self.nxt_name = Name(nxt_name) 2077 self.type_bitmaps = TypeBitmaps(type_bitmaps) 2078 self.ttl = str2time(ttl) 2079 2080 def encode(self, strio, compDict = None): 2081 self.nxt_name.encode(strio, None) 2082 self.type_bitmaps.encode(strio, None) 2083 2084 def decode(self, strio, length=None): 2085 start = strio.tell() 2086 self.nxt_name.decode(strio, None) 2087 here = strio.tell() 2088 self.type_bitmaps.decode(strio, length + start - here if length else None) 2089 2090 def __hash__(self): 2091 return hash((self.nxt_name, self.type_bitmaps)) 2092 2093 class Record_NSEC3PARAM(tputil.FancyEqMixin, tputil.FancyStrMixin): 2094 """ 2095 A DNSSEC NSEC3PARAM record contains the NSEC3 parameters (hash algorithm, 2096 flags, iterations and salt) needed by authoritative servers to calculate 2097 hashed owner names. The presence of an NSEC3PARAM RR at a zone apex 2098 indicates that the specified parameters may be used by authoritative 2099 servers to choose an appropriate set of NSEC3 RRs for negative responses. 2100 2101 @type hash_algo: C{int} 2102 @ivar hash_algo: Identifies the cryptographic hash algorithm used to construct the hash value. 2103 2104 @type flags: C{int} 2105 @ivar flags: Identifies 8 1-bit flags. The only flag presently defined is the 2106 opt-out flag. If the opt-out flag is set, the NSEC3 record covers zero or more unsigned 2107 delegations. If the opt-out flag is clear, the NSEC3 record covers zero unsigned delegations. 2108 2109 @type iterations: C{int} 2110 @ivar iterations: Defines the nubmer of additional times the hash algorithm has been performed. 2111 2112 @type salt: L{Charset} 2113 @ivar salt: Identifies the salt value provided to the hash. 2114 2115 @type ttl: C{int} 2116 @ivar ttl: The maximum number of seconds which this record should be 2117 cached. 2118 """ 2119 implements(IEncodable, IRecord) 2120 TYPE = NSEC3 2121 fmt = '!BBH' 2122 2123 fancybasename = 'NSEC3' 2124 showAttributes = ('hash_algo', 'flags', 'iterations', ('_salt', 'salt', '%s'), 'ttl') 2125 compareAttributes = ('hash_algo', 'flags', 'iterations', 'salt', 'ttl') 2126 2127 _salt = property(lambda self: self.salt.string) 2128 2129 def __init__(self, hash_algo=0, flags=0, iterations=0, salt='', ttl=None): 2130 self.hash_algo = hash_algo 2131 self.flags = flags 2132 self.iterations = iterations 2133 self.salt = Charstr(salt) 2134 self.ttl = str2time(ttl) 2135 2136 def encode(self, strio, compDict = None): 2137 strio.write(struct.pack(self.fmt, 2138 self.hash_algo, 2139 self.flags, 2140 self.iterations)) 2141 self.salt.encode(strio, None) 2142 2143 def decode(self, strio, length=None): 2144 start = strio.tell() 2145 l = struct.calcsize(self.fmt) 2146 buff = readPrecisely(strio, l) 2147 r = struct.unpack(self.fmt, buff) 2148 self.hash_algo, self.flags, self.iterations = r 2149 self.salt.decode(strio) 2150 here = strio.tell() 2151 2152 def __hash__(self): 2153 return hash((self.hash_algo, self.flags, self.iterations, self.salt)) 2154 2155 class Record_NSEC3(Record_NSEC3PARAM): 2156 """ 2157 A DNSSEC NSEC3 record provides non-zone-enumerable authenticated denial of existance 2158 for DNS data and permits a gradual expansion of delegation-centric zones. 2159 2160 A DNSSEC NSEC3 record lists: 2161 2162 1) the set of RR types present at the original owner name of the NSEC RR. 2163 2164 2) the next hashed owner name in the hash order of the zone. 2165 2166 @type hash_algo: C{int} 2167 @ivar hash_algo: Identifies the cryptographic hash algorithm used to construct the hash value. 2168 2169 @type flags: C{int} 2170 @ivar flags: Identifies 8 1-bit flags. The only flag presently defined is the 2171 opt-out flag. If the opt-out flag is set, the NSEC3 record covers zero or more unsigned 2172 delegations. If the opt-out flag is clear, the NSEC3 record covers zero unsigned delegations. 2173 2174 @type iterations: C{int} 2175 @ivar iterations: Defines the nubmer of additional times the hash algorithm has been performed. 2176 2177 @type salt: L{Charset} 2178 @ivar salt: Identifies the salt value provided to the hash. 2179 2180 @type nxt_hash_owner_name: L{Charset} 2181 @ivar nxt_hash_owner_name: Contains the next hashed owner name in the zone in hash order. 2182 2183 @type type_bitmaps: L{TypeBitmaps} 2184 @ivar type_bitmaps: Identifies the RRset types that exist at the NSEC3 RR's original owner name. 2185 2186 @type ttl: C{int} 2187 @ivar ttl: The maximum number of seconds which this record should be 2188 cached. 2189 """ 2190 implements(IEncodable, IRecord) 2191 TYPE = NSEC3 2192 fmt = '!BBH' 2193 2194 fancybasename = 'NSEC3' 2195 showAttributes = ('hash_algo', 'flags', 'iterations', ('_salt', 'salt', '%s'), ('nxt_hash_owner_name', 'nxt_hash_owner_name', '%s'), ('_type_bitmaps', 'type_bitmaps', '%s'), 'ttl') 2196 compareAttributes = ('hash_algo', 'flags', 'iterations', 'salt', 'nxt_hash_owner_name', 'type_bitmaps', 'ttl') 2197 2198 _salt = property(lambda self: self.salt.string) 2199 _type_bitmaps = property(lambda self: self.type_bitmaps.string) 2200 2201 def __init__(self, hash_algo=0, flags=0, iterations=0, salt='', nxt_hash_owner='', type_bitmaps=None, ttl=None): 2202 Record_NSEC3PARAM.__init__( self, hash_algo, flags, iterations, salt, ttl) 2203 self.nxt_hash_owner_name = Charstr(nxt_hash_owner) 2204 self.type_bitmaps = TypeBitmaps(type_bitmaps) 2205 2206 def encode(self, strio, compDict = None): 2207 Record_NSEC3PARAM.encode(self, strio, compDict) 2208 self.nxt_hash_owner_name.encode(strio, None) 2209 self.type_bitmaps.encode(strio, None) 2210 2211 def decode(self, strio, length=None): 2212 start = strio.tell() 2213 Record_NSEC3PARAM.decode(self, strio, compDict) 2214 self.nxt_hash_owner_name.decode(strio) 2215 here = strio.tell() 2216 self.type_bitmaps.decode(strio, length + start - here if length else None) 2217 2218 def __hash__(self): 2219 return hash((self.hash_algo, self.flags, self.iterations, self.salt, 2220 self.nxt_hash_owner_name, self.type_bitmaps)) 2221 1471 2222 # This is a fallback record 1472 2223 class UnknownRecord(tputil.FancyEqMixin, tputil.FancyStrMixin, object): 1473 2224 """ … … 1544 2295 queries = answers = add = ns = None 1545 2296 1546 2297 def __init__(self, id=0, answer=0, opCode=0, recDes=0, recAv=0, 1547 auth=0, rCode=OK, trunc=0, maxSize=512):2298 auth=0, rCode=OK, trunc=0, maxSize=512, authData=0, chkDis=0): 1548 2299 self.maxSize = maxSize 1549 2300 self.id = id 1550 2301 self.answer = answer 1551 2302 self.opCode = opCode 1552 self.auth = auth 1553 self.trunc = trunc 1554 self.recDes = recDes 1555 self.recAv = recAv 2303 self.auth = auth #AA - Authoritative Answer 2304 self.trunc = trunc #TC - TrunCated 2305 self.recDes = recDes #RD - Recursion Desired 2306 self.recAv = recAv #RA - Recursion Available 2307 self.authData = authData #AD - Authentic Data 2308 self.chkDis = chkDis #CD - Checking Disabled 1556 2309 self.rCode = rCode 1557 2310 self.queries = [] 1558 2311 self.answers = [] … … 1597 2350 | ((self.auth & 1 ) << 2 ) 1598 2351 | ((self.trunc & 1 ) << 1 ) 1599 2352 | ( self.recDes & 1 ) ) 1600 byte4 = ( ( (self.recAv & 1 ) << 7 ) 2353 byte4 = ( ((self.recAv & 1 ) << 7 ) 2354 |((self.authData & 1 ) << 5 ) 2355 |((self.chkDis & 1 ) << 4 ) 1601 2356 | (self.rCode & 0xf ) ) 1602 2357 1603 2358 strio.write(struct.pack(self.headerFmt, self.id, byte3, byte4, … … 1617 2372 self.trunc = ( byte3 >> 1 ) & 1 1618 2373 self.recDes = byte3 & 1 1619 2374 self.recAv = ( byte4 >> 7 ) & 1 2375 self.authData = ( byte4 >> 5 ) & 1 2376 self.chkDis = ( byte4 >> 4 ) & 1 1620 2377 self.rCode = byte4 & 0xf 1621 2378 1622 2379 self.queries = [] … … 1635 2392 1636 2393 def parseRecords(self, list, num, strio): 1637 2394 for i in range(num): 1638 header = RRHeader()1639 2395 try: 1640 header .decode(strio)2396 header = OPTHeader.factory(strio) 1641 2397 except EOFError: 1642 2398 return 1643 2399 t = self.lookupRecordType(header.type) -
names/serialNumberArithmetic.py
1 #!/usr/bin/env python 2 # 3 # RFC 1982 DNS Serial Number Arithmetic 4 # RFC 4034 DNSSEC Signature Expiration and Inception Fields 5 # 6 # bob.novas@shinkuro.com 7 # 8 9 class SNA(object): 10 """ 11 implements RFC 1982 - DNS Serial Number Arithmetic 12 """ 13 SERIAL_BITS = 32 14 MODULOVAL = 2**SERIAL_BITS 15 HLFRNG = 2**(SERIAL_BITS-1) 16 MAXADD = (2**(SERIAL_BITS-1)-1) 17 18 def __init__(self, number): 19 self._number = int(number)%self.MODULOVAL 20 21 def __repr__(self): 22 return str(self._number) 23 24 def EQ(self, sna2): 25 assert isinstance(sna2, SNA) 26 return sna2._number == self._number 27 28 def LT(self, sna2): 29 assert isinstance(sna2, SNA) 30 return not self.EQ(sna2) and \ 31 ((self._number < sna2._number) and ((sna2._number - self._number) < self.HLFRNG) or \ 32 (self._number > sna2._number) and ((self._number - sna2._number) > self.HLFRNG)) 33 34 def GT(self, sna2): 35 assert isinstance(sna2, SNA) 36 return not self.EQ(sna2) and \ 37 ((self._number < sna2._number) and ((sna2._number - self._number) > self.HLFRNG) or \ 38 (self._number > sna2._number) and ((self._number - sna2._number) < self.HLFRNG)) 39 40 def LE(self, sna2): 41 return self.EQ(sna2) or self.LT(sna2) 42 43 def GE(self, sna2): 44 return self.EQ(sna2) or self.GT(sna2) 45 46 def Add(self, sna2): 47 assert isinstance(sna2, SNA) 48 if sna2.LE(SNA(self.MAXADD)): 49 return SNA( (self._number + sna2._number)%self.MODULOVAL ) 50 else: 51 raise ArithmeticError 52 53 def __hash__(self): 54 return hash(self._number) 55 56 __eq__ = EQ 57 __lt__ = LT 58 __gt__ = GT 59 __le__ = LE 60 __ge__ = GE 61 __add__ = Add 62 63 @staticmethod 64 def Max(snaList): 65 """ 66 this takes a list of sna's from which it will pick the sn with the highest value 67 """ 68 if len(snaList) == 0: 69 return None 70 trialMax = snaList[0] 71 for s in snaList[1:]: 72 if not trialMax: 73 trialMax = s 74 elif s and s.GT(trialMax): 75 trialMax = s 76 return trialMax 77 78 import calendar, time 79 class DateSNA(SNA): 80 """ 81 implements DNS Serial Number Arithmetic 82 for dates 'YYYYMMDDHHMMSS' per RFC 4034 P3.1.5 83 """ 84 fmt = '%Y%m%d%H%M%S' 85 86 def __init__(self, utcDateTime=''): 87 ''' 88 accept a UTC date/time string as YYMMDDHHMMSS 89 and convert it to seconds since the epoch 90 ''' 91 if not utcDateTime: 92 utcDateTime = '19700101000000' 93 dtstruct = time.strptime(utcDateTime, DateSNA.fmt) 94 assert dtstruct.tm_year < 1970+136 95 secondsSinceE = calendar.timegm(dtstruct) 96 super(DateSNA, self).__init__(secondsSinceE) 97 98 def Add(self, sna2): 99 if not isinstance(sna2, SNA): 100 return NotImplemented 101 102 if sna2.LE(SNA(self.MAXADD)) and (self._number + sna2._number < self.MODULOVAL): 103 sna = SNA((self._number + sna2._number)%self.MODULOVAL) 104 return DateSNA.fromSNA(sna) 105 else: 106 raise ArithmeticError 107 108 def asDate(self): 109 dtstruct = time.gmtime(self._number) 110 return time.strftime(DateSNA.fmt, dtstruct) 111 112 def asInt(self): 113 return self._number 114 115 @staticmethod 116 def fromSNA(sna): 117 assert isinstance(sna, SNA) 118 d = DateSNA() 119 d._number = sna._number 120 return d 121 122 @staticmethod 123 def fromInt(i): 124 return DateSNA.fromSNA(SNA(i)) 125 126 def __str__(self): 127 return self.asDate() 128 129 130 if __name__ == "__main__": 131 132 s1 = SNA(1) 133 s1a = SNA(1) 134 s2 = SNA(2) 135 136 assert s1 == s1a 137 assert hash(s1) == hash(s1a) 138 assert s1 <= s1a 139 assert s1 >= s1a 140 assert s1 < s2 141 assert not s1 > s2 142 assert s1 <= s2 143 assert not s1 >= s2 144 145 smaxval = SNA(SNA.HLFRNG+SNA.HLFRNG-1) 146 smaxplus1 = smaxval.Add(s1) 147 smaxadd = SNA(SNA.MAXADD) 148 149 assert smaxplus1 > smaxval 150 assert s1 + smaxadd 151 assert SNA.Max([None, s1]) == s1 152 assert SNA.Max([s1, None]) == s1 153 154 date1 = DateSNA('20120101000000') 155 date2 = DateSNA('20130101000000') 156 assert date1 < date2 157 158 date3 = DateSNA('20370101000000') 159 sna1 = SNA(365*24*60*60) 160 date4 = date3 + sna1 161 assert date4._number == date3._number + sna1._number 162 163 date5 = DateSNA() 164 date6 = date5 + SNA(24*60*60) 165 assert date6._number == date5._number + 24*60*60 166 167 date7 = DateSNA('20370101000000') 168 date8 = date7 + sna1 169 assert date8._number == date7._number + sna1._number 170 171 172 No newline at end of file -
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. … … 386 458 Initialize the controller: create a list of messages. 387 459 """ 388 460 self.messages = [] 461 self.dnssecConfig = common.DnssecConfig() 389 462 390 463 391 464 def messageReceived(self, msg, proto, addr): … … 840 913 repr(dns.UnknownRecord("foo\x1fbar", 12)), 841 914 "<UNKNOWN data='foo\\x1fbar' ttl=12>") 842 915 916 def test_dnskey(self): 917 """ 918 The repr of a L{dns.DNSKEY} instance includes the flags, protocol, 919 algo, pub_key and ttl fields of the record. 920 """ 921 self.assertEqual( 922 repr(dns.Record_DNSKEY(10, 20, 30, "foo\x1fbar", ttl=20)), 923 "<DNSKEY flags=10 protocol=20 algo=30 pub_key=foo\x1fbar ttl=20>") 924 925 def test_ds(self): 926 """ 927 The repr of a L{dns.DS} instance includes the key_tag, algo, digest_type, 928 digest and ttl fields of the record. 929 """ 930 self.assertEqual( 931 repr(dns.Record_DS(11, 22, 33, "foo\x1fbar1", ttl=21)), 932 "<DS key_tag=11 algo=22 digest_type=33 digest=foo\x1fbar1 ttl=21>") 933 934 def test_nsec(self): 935 """ 936 The repr of a L{dns.NSEC} instance includes the nxt_name, type_bitmaps and 937 ttl fields of the record. 938 """ 939 self.assertEqual( 940 repr(dns.Record_NSEC('bob', "\x1fabcd", ttl=31)), 941 "<NSEC nxt_name=bob type_bitmaps=\x1fabcd ttl=31>") 942 943 def test_nsec3param(self): 944 """ 945 The repr of a L{dns.NSEC3PARAM} instance includes the hash_algo, flags, 946 iterations, salt and ttl fields of the record. 947 """ 948 self.assertEqual( 949 repr(dns.Record_NSEC3PARAM(1, 2, 3, '\x12\x34', ttl=31)), 950 "<NSEC3 hash_algo=1 flags=2 iterations=3 salt=\x12\x34 ttl=31>") 951 952 def test_nsec3(self): 953 """ 954 The repr of a L{dns.NSEC3} instance includes the hash_algo, flags, iterations, 955 salt, nxt_hash_owner_name, type_bitmaps and ttl fields of the record. 956 """ 957 self.assertEqual( 958 repr(dns.Record_NSEC3(1, 2, 3, '\x12\x34', 'bob', "\x1fabcd", ttl=31)), 959 "<NSEC3 hash_algo=1 flags=2 iterations=3 salt=\x12\x34 nxt_hash_owner_name=bob type_bitmaps=\x1fabcd ttl=31>") 960 961 def test_opt(self): 962 """ 963 The repr of a L{dns.OPT} instance includes the payload_size, dnssecOk flag, 964 and version fields of the record. (The OPT record has no ttl field.) 965 """ 966 self.assertEqual( 967 repr(dns.Record_OPT(payload_size=1492, dnssecOk=1, version=0)), 968 "<OPT payload_size=1492 flags=0x8000 version=0>") 843 969 970 def test_rrsig(self): 971 """ 972 The repr of a L{dns.RRSIG} instance includes the algo, labels, original_ttl 973 sig_expiration, sig_inception, key_tag, signers_name, signature and ttl 974 fields of the record. 975 """ 976 self.assertEqual( 977 repr(dns.Record_RRSIG(type_covered=dns.A, 978 algo=2, 979 labels=3, 980 original_ttl=30, 981 sig_expiration='20110101123456', 982 sig_inception= '20110202112233', 983 key_tag=60, 984 signers_name='bob', 985 signature='\x12\x34sig', 986 ttl=70)), 987 "<RRSIG type_covered=1 algo=2 labels=3 original_ttl=30" 988 + " sig_expiration=20110101123456 sig_inception=20110202112233 key_tag=60" 989 + " signers_name=bob signature=\x12\x34sig ttl=70>") 844 990 845 991 class _Equal(object): 846 992 """ … … 908 1054 cls('example.com', 123), 909 1055 cls('example.org', 123)) 910 1056 1057 def test_optheader(self): 1058 """ 1059 Two OptHeader instances comapare equal iff the have the same 1060 (Record_OPT) payload and auth bit. 1061 """ 1062 self._equalityTest( 1063 dns.OPTHeader(payload=dns.Record_OPT(payload_size=1024, dnssecOk=True, version=0, ttl=30)), 1064 dns.OPTHeader(payload=dns.Record_OPT(payload_size=1024, dnssecOk=True, version=0, ttl=30)), 1065 dns.OPTHeader(payload=dns.Record_OPT(payload_size=1492, dnssecOk=False, version=0, ttl=40), auth=True)) 911 1066 912 1067 def test_rrheader(self): 913 1068 """ … … 1430 1585 dns.UnknownRecord('foo', ttl=10), 1431 1586 dns.UnknownRecord('foo', ttl=10), 1432 1587 dns.UnknownRecord('foo', ttl=100)) 1588 1589 def test_rrsig(self): 1590 """ 1591 L(dns.RRSIG) instances compare equal iff they have the same 1592 type_covered, algo, labels, original_ttl, sig_expiration, sig_inception, 1593 key_tag, signers_name, signature, and ttl 1594 """ 1595 self._equalityTest( 1596 dns.Record_RRSIG(type_covered=dns.A), 1597 dns.Record_RRSIG(type_covered=dns.A), 1598 dns.Record_RRSIG(type_covered=dns.AAAA)) 1599 self._equalityTest( 1600 dns.Record_RRSIG(algo=1), 1601 dns.Record_RRSIG(algo=1), 1602 dns.Record_RRSIG(algo=2)) 1603 self._equalityTest( 1604 dns.Record_RRSIG(labels=3), 1605 dns.Record_RRSIG(labels=3), 1606 dns.Record_RRSIG(labels=4)) 1607 self._equalityTest( 1608 dns.Record_RRSIG(original_ttl=5), 1609 dns.Record_RRSIG(original_ttl=5), 1610 dns.Record_RRSIG(original_ttl=6)) 1611 self._equalityTest( 1612 dns.Record_RRSIG(sig_expiration='20110101000000'), 1613 dns.Record_RRSIG(sig_expiration='20110101000000'), 1614 dns.Record_RRSIG(sig_expiration='20110101000001')) 1615 self._equalityTest( 1616 dns.Record_RRSIG(sig_inception='20120101000000'), 1617 dns.Record_RRSIG(sig_inception='20120101000000'), 1618 dns.Record_RRSIG(sig_inception='20120101000001')) 1619 self._equalityTest( 1620 dns.Record_RRSIG(key_tag=11), 1621 dns.Record_RRSIG(key_tag=11), 1622 dns.Record_RRSIG(key_tag=12)) 1623 self._equalityTest( 1624 dns.Record_RRSIG(signers_name='bob'), 1625 dns.Record_RRSIG(signers_name='bob'), 1626 dns.Record_RRSIG(signers_name='joe')) 1627 self._equalityTest( 1628 dns.Record_RRSIG(signature='abcdef'), 1629 dns.Record_RRSIG(signature='abcdef'), 1630 dns.Record_RRSIG(signature='abcdefg')) 1631 self._equalityTest( 1632 dns.Record_RRSIG(ttl=10), 1633 dns.Record_RRSIG(ttl=10), 1634 dns.Record_RRSIG(ttl=20)) 1635 1636 def test_ds(self): 1637 """ 1638 L(dns.DS) instances compare equal iff they have the same 1639 key_tag, algo, digest_type, digest and ttl 1640 """ 1641 self._equalityTest( 1642 dns.Record_DS(key_tag=1), 1643 dns.Record_DS(key_tag=1), 1644 dns.Record_DS(key_tag=2)) 1645 self._equalityTest( 1646 dns.Record_DS(algo=3), 1647 dns.Record_DS(algo=3), 1648 dns.Record_DS(algo=4)) 1649 self._equalityTest( 1650 dns.Record_DS(digest_type=5), 1651 dns.Record_DS(digest_type=5), 1652 dns.Record_DS(digest_type=6)) 1653 self._equalityTest( 1654 dns.Record_DS(digest='abcdef-digest'), 1655 dns.Record_DS(digest='abcdef-digest'), 1656 dns.Record_DS(digest='abcdef-digest-f')) 1657 self._equalityTest( 1658 dns.Record_DS(ttl=10), 1659 dns.Record_DS(ttl=10), 1660 dns.Record_DS(ttl=20)) 1661 1662 def test_dnskey(self): 1663 """ 1664 L(dns.DNSKEY) instances compare equal iff they have the same 1665 flags, protocol, algo, pub_key and ttl 1666 """ 1667 self._equalityTest( 1668 dns.Record_DNSKEY(flags=1), 1669 dns.Record_DNSKEY(flags=1), 1670 dns.Record_DNSKEY(flags=2)) 1671 self._equalityTest( 1672 dns.Record_DNSKEY(protocol=3), 1673 dns.Record_DNSKEY(protocol=3), 1674 dns.Record_DNSKEY(protocol=4)) 1675 self._equalityTest( 1676 dns.Record_DNSKEY(algo=5), 1677 dns.Record_DNSKEY(algo=5), 1678 dns.Record_DNSKEY(algo=6)) 1679 self._equalityTest( 1680 dns.Record_DNSKEY(pub_key='abcdef-digest'), 1681 dns.Record_DNSKEY(pub_key='abcdef-digest'), 1682 dns.Record_DNSKEY(pub_key='abcdef-digest-f')) 1683 self._equalityTest( 1684 dns.Record_DNSKEY(ttl=10), 1685 dns.Record_DNSKEY(ttl=10), 1686 dns.Record_DNSKEY(ttl=20)) 1687 1688 def test_nsec(self): 1689 """ 1690 L(dns.DNSKEY) instances compare equal iff they have the same 1691 nxt_name, type_bitmaps and ttl 1692 """ 1693 self._equalityTest( 1694 dns.Record_NSEC(nxt_name="example.com"), 1695 dns.Record_NSEC(nxt_name="example.com"), 1696 dns.Record_NSEC(nxt_name="a.example.com")) 1697 self._equalityTest( 1698 dns.Record_NSEC(type_bitmaps="A AAAA NS NSEC3"), 1699 dns.Record_NSEC(type_bitmaps="A AAAA NS NSEC3"), 1700 dns.Record_NSEC(type_bitmaps="A AAAA NS NSEC3 RRSIG")) 1701 self._equalityTest( 1702 dns.Record_NSEC(ttl=5), 1703 dns.Record_NSEC(ttl=5), 1704 dns.Record_NSEC(ttl=6)) 1705 1706 def test_nsec3param(self): 1707 """ 1708 L(dns.DNSKEY) instances compare equal iff they have the same 1709 hash_algo, flags, iterations, salt, nxt_hash_owner_name, type_bitmaps and ttl 1710 """ 1711 self._equalityTest( 1712 dns.Record_NSEC3PARAM(hash_algo=1), 1713 dns.Record_NSEC3PARAM(hash_algo=1), 1714 dns.Record_NSEC3PARAM(hash_algo=2)) 1715 self._equalityTest( 1716 dns.Record_NSEC3PARAM(flags=1), 1717 dns.Record_NSEC3PARAM(flags=1), 1718 dns.Record_NSEC3PARAM(flags=2)) 1719 self._equalityTest( 1720 dns.Record_NSEC3PARAM(iterations=5), 1721 dns.Record_NSEC3PARAM(iterations=5), 1722 dns.Record_NSEC3PARAM(iterations=6)) 1723 self._equalityTest( 1724 dns.Record_NSEC3PARAM(salt="abcdef"), 1725 dns.Record_NSEC3PARAM(salt="abcdef"), 1726 dns.Record_NSEC3PARAM(salt="abcdefg")) 1727 self._equalityTest( 1728 dns.Record_NSEC3PARAM(ttl=5), 1729 dns.Record_NSEC3PARAM(ttl=5), 1730 dns.Record_NSEC3PARAM(ttl=6)) 1731 1732 def test_nsec3(self): 1733 """ 1734 L(dns.DNSKEY) instances compare equal iff they have the same 1735 hash_algo, flags, iterations, salt, nxt_hash_owner_name, type_bitmaps and ttl 1736 """ 1737 self._equalityTest( 1738 dns.Record_NSEC3(hash_algo=1), 1739 dns.Record_NSEC3(hash_algo=1), 1740 dns.Record_NSEC3(hash_algo=2)) 1741 self._equalityTest( 1742 dns.Record_NSEC3(flags=1), 1743 dns.Record_NSEC3(flags=1), 1744 dns.Record_NSEC3(flags=2)) 1745 self._equalityTest( 1746 dns.Record_NSEC3(iterations=5), 1747 dns.Record_NSEC3(iterations=5), 1748 dns.Record_NSEC3(iterations=6)) 1749 self._equalityTest( 1750 dns.Record_NSEC3(salt="abcdef"), 1751 dns.Record_NSEC3(salt="abcdef"), 1752 dns.Record_NSEC3(salt="abcdefg")) 1753 self._equalityTest( 1754 dns.Record_NSEC3(nxt_hash_owner="example.com"), 1755 dns.Record_NSEC3(nxt_hash_owner="example.com"), 1756 dns.Record_NSEC3(nxt_hash_owner="a.example.com")) 1757 self._equalityTest( 1758 dns.Record_NSEC3(type_bitmaps="A AAAA NS NSEC3"), 1759 dns.Record_NSEC3(type_bitmaps="A AAAA NS NSEC3"), 1760 dns.Record_NSEC3(type_bitmaps="A AAAA NS NSEC3 RRSIG")) 1761 self._equalityTest( 1762 dns.Record_NSEC3(ttl=5), 1763 dns.Record_NSEC3(ttl=5), 1764 dns.Record_NSEC3(ttl=6)) 1765 1766 1767 1768 No newline at end of file