Ticket #5454: AddEDNS0andDNSSEC5454.patch
| File AddEDNS0andDNSSEC5454.patch, 79.3 KB (added by BobNovas, 15 months ago) |
|---|
-
names/client.py
71 71 protocol = property(_getProtocol) 72 72 73 73 74 def __init__(self, resolv=None, servers=None, timeout=(1, 3, 11, 45), reactor=None): 74 def __init__(self, 75 resolv=None, 76 servers=None, 77 timeout=(1, 3, 11, 45), 78 reactor=None, 79 dnssecConfig=None): 75 80 """ 76 81 Construct a resolver which will query domain name servers listed in 77 82 the C{resolv.conf(5)}-format file given by C{resolv} as well as … … 98 103 L{IReactorTCP} which will be used to establish connections, listen 99 104 for DNS datagrams, and enforce timeouts. If not provided, the 100 105 global reactor will be used. 106 107 @param dnssecConfig: An L{DnssecConfig} - see common.DnssecConfig() 101 108 102 109 @raise ValueError: Raised if no nameserver addresses can be found. 103 110 """ 104 common.ResolverBase.__init__(self )111 common.ResolverBase.__init__(self, dnssecConfig) 105 112 106 113 if reactor is None: 107 114 from twisted.internet import reactor … … 381 388 return self.queryTCP(message.queries).addCallback(self.filterAnswers) 382 389 if message.rCode != dns.OK: 383 390 return failure.Failure(self.exceptionForCode(message.rCode)(message)) 384 return (message.answers, message.authority, message.additional) 391 392 #if dnssecOk is enabled, return a reference to the message as the 4th member of 393 #the tuple, so the caller can access the message header flags. There are more 394 #flags than just AD (authentic Data) that are set in a response. 395 if self.dnssecConfig.dnssecOk: 396 return (message.answers, message.authority, message.additional, message) 397 else: 398 #dnssecOk was not requested - return a legacy 3-tuple 399 return (message.answers, message.authority, message.additional) 385 400 386 401 387 402 def _lookup(self, name, cls, type, timeout): … … 953 968 @rtype: C{Deferred} 954 969 """ 955 970 return getResolver().lookupNamingAuthorityPointer(name, timeout) 971 972 973 def lookupDNSKey(name, timeout=None): 974 """ 975 DNSKEY lookup. 976 977 @type name: C{str} 978 @param name: DNS name to resolve. 979 980 @type timeout: Sequence of C{int} 981 @param timeout: Number of seconds after which to reissue the query. 982 When the last timeout expires, the query is considered failed. 983 984 @rtype: C{Deferred} 985 """ 986 return getResolver().lookupDNSKey(name, timeout) 987 988 989 def lookupDS(name, timeout=None): 990 """ 991 DS lookup. 992 993 @type name: C{str} 994 @param name: DNS name to resolve. 995 996 @type timeout: Sequence of C{int} 997 @param timeout: Number of seconds after which to reissue the query. 998 When the last timeout expires, the query is considered failed. 999 1000 @rtype: C{Deferred} 1001 """ 1002 return getResolver().lookupDS(name, timeout) 1003 1004 1005 def lookupNSEC(name, timeout=None): 1006 """ 1007 NSEC lookup. 1008 1009 @type name: C{str} 1010 @param name: DNS name to resolve. 1011 1012 @type timeout: Sequence of C{int} 1013 @param timeout: Number of seconds after which to reissue the query. 1014 When the last timeout expires, the query is considered failed. 1015 1016 @rtype: C{Deferred} 1017 """ 1018 return getResolver().lookupNSEC(name, timeout) 1019 1020 1021 def lookupNSEC3(name, timeout=None): 1022 """ 1023 NSEC3 lookup. 1024 1025 @type name: C{str} 1026 @param name: DNS name to resolve. 1027 1028 @type timeout: Sequence of C{int} 1029 @param timeout: Number of seconds after which to reissue the query. 1030 When the last timeout expires, the query is considered failed. 1031 1032 @rtype: C{Deferred} 1033 """ 1034 return getResolver().lookupNSEC3(name, timeout) 1035 1036 1037 def lookupNSEC3Param(name, timeout=None): 1038 """ 1039 NSEC3 Param lookup. 1040 1041 @type name: C{str} 1042 @param name: DNS name to resolve. 1043 1044 @type timeout: Sequence of C{int} 1045 @param timeout: Number of seconds after which to reissue the query. 1046 When the last timeout expires, the query is considered failed. 1047 1048 @rtype: C{Deferred} 1049 """ 1050 return getResolver().lookupNSEC3Param(name, timeout) 1051 1052 1053 def lookupRRSIG(name, timeout=None): 1054 """ 1055 RRSIG lookup. 1056 1057 @type name: C{str} 1058 @param name: DNS name to resolve. 1059 1060 @type timeout: Sequence of C{int} 1061 @param timeout: Number of seconds after which to reissue the query. 1062 When the last timeout expires, the query is considered failed. 1063 1064 @rtype: C{Deferred} 1065 """ 1066 return getResolver().lookupRRSIG(name, timeout) -
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 """ 52 def __init__(self, 53 recDes=True, 54 ednsEnabled=False, 55 maxUdpPktSz=512, 56 dnssecOk=False, 57 chkDis=False, 58 version=0): 59 60 self.recDes = recDes 61 self.ednsEnabled = ednsEnabled 62 self.maxUdpPktSz = maxUdpPktSz 63 self.dnssecOk = dnssecOk 64 self.chkDis = chkDis 65 self.version = version 66 67 assert not self.ednsEnabled or 512 <= self.maxUdpPktSz <= 65535 68 assert version == 0 69 21 70 class ResolverBase: 22 71 """ 23 72 L{ResolverBase} is a base class for L{IResolver} implementations which … … 36 85 37 86 typeToMethod = None 38 87 39 def __init__(self ):88 def __init__(self, dnssecConfig=None): 40 89 self.typeToMethod = {} 41 90 for (k, v) in typeToMethod.items(): 42 91 self.typeToMethod[k] = getattr(self, v) 92 self.dnssecConfig = dnssecConfig 93 if self.dnssecConfig == None: 94 self.dnssecConfig = DnssecConfig() 43 95 44 45 96 def exceptionForCode(self, responseCode): 46 97 """ 47 98 Convert a response code (one of the possible values of … … 200 251 @see: twisted.names.client.lookupAllRecords 201 252 """ 202 253 return self._lookup(name, dns.IN, dns.ALL_RECORDS, timeout) 254 203 255 256 def lookupDNSKey(self, name, timeout=None): 257 """ 258 @see: twisted.names.client.lookupDNSKey 259 """ 260 return self._lookup(name, dns.IN, dns.DNSKEY, timeout) 261 262 263 def lookupDS(self, name, timeout=None): 264 """ 265 @see: twisted.names.client.lookupDS 266 """ 267 return self._lookup(name, dns.IN, dns.DS, timeout) 268 269 270 def lookupNSEC(self, name, timeout=None): 271 """ 272 @see: twisted.names.client.lookupNSEC 273 """ 274 return self._lookup(name, dns.IN, dns.NSEC, timeout) 275 276 277 def lookupNSEC3(self, name, timeout=None): 278 """ 279 @see: twisted.names.client.lookupNSEC3 280 """ 281 return self._lookup(name, dns.IN, dns.NSEC3, timeout) 282 283 284 def lookupNSEC3Param(self, name, timeout=None): 285 """ 286 @see: twisted.names.client.lookupNSEC3Param 287 """ 288 return self._lookup(name, dns.IN, dns.NSEC3PARAM, timeout) 289 290 291 def lookupRRSIG(self, name, timeout=None): 292 """ 293 @see: twisted.names.client.lookupRRSIG 294 """ 295 return self._lookup(name, dns.IN, dns.RRSIG, timeout) 296 297 204 298 def getHostByName(self, name, timeout = None, effort = 10): 205 299 """ 206 300 @see: twisted.names.client.getHostByName … … 268 362 dns.MX: 'lookupMailExchange', 269 363 dns.TXT: 'lookupText', 270 364 dns.SPF: 'lookupSenderPolicy', 365 dns.DNSKEY:'lookupDNSKey', 366 dns.DS: 'lookupDS', 367 dns.NSEC: 'lookupNSEC', 368 dns.NSEC3: 'lookupNSEC3', 369 dns.NSEC3PARAM: 'lookupNSEC3Param', 370 dns.RRSIG: 'lookupRRSIG', 271 371 272 372 dns.RP: 'lookupResponsibility', 273 373 dns.AFSDB: 'lookupAFSDatabase', -
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 49 52 import struct, random, types, socket 50 53 51 54 import cStringIO as StringIO … … 54 57 55 58 from zope.interface import implements, Interface, Attribute 56 59 60 from base64 import b64decode, b64encode 57 61 58 62 # Twisted imports 59 63 from twisted.internet import protocol, defer … … 61 65 from twisted.python import log, failure 62 66 from twisted.python import util as tputil 63 67 from twisted.python import randbytes 68 from twisted.names.ser_num_arith import SNA, DateSNA 64 69 65 70 66 71 def randomSource(): … … 79 84 NAPTR = 35 80 85 A6 = 38 81 86 DNAME = 39 87 OPT = 41 88 DS = 43 89 RRSIG = 46 90 NSEC = 47 91 DNSKEY = 48 92 NSEC3 = 50 93 NSEC3PARAM = 51 82 94 SPF = 99 83 95 84 96 QUERY_TYPES = { … … 108 120 NAPTR: 'NAPTR', 109 121 A6: 'A6', 110 122 DNAME: 'DNAME', 111 SPF: 'SPF' 123 OPT: 'OPT', 124 DS: 'DS', 125 RRSIG: 'RRSIG', 126 NSEC: 'NSEC', 127 DNSKEY: 'DNSKEY', 128 NSEC3: 'NSEC3', 129 NSEC3PARAM: 'NSEC3PARAM', 130 SPF: 'SPF', 112 131 } 113 132 114 133 IXFR, AXFR, MAILB, MAILA, ALL_RECORDS = range(251, 256) … … 370 389 371 390 def __str__(self): 372 391 return self.name 392 393 class Sigstr(object): 394 ''' 395 for signatures and keys. display as b64 encoded 396 ''' 397 implements(IEncodable) 398 399 def __init__(self, string=''): 400 if not isinstance(string, str): 401 raise ValueError("%r is not a string" % (string, )) 402 self.string = string #b64encoded string 403 404 def encode(self, strio, compDict=None): 405 ''' 406 Write the byte representation (the un-b64-encoded string) 407 to the file. 408 409 @type strio: file 410 @param srio: The byte representation of this signature or key 411 will be written to this file 412 413 @type compDict: dict 414 @param compDict: not used. 415 ''' 416 strio.write(b64decode(self.string)) 417 418 def decode(self, strio, length=None): 419 ''' 420 Decode a signature or a key. 373 421 422 @type strio: file 423 @param strio: Exactly length bytes will be read from this file 424 to decode the full signature or key 425 426 @type length: int 427 @param lenth: length must always be given. A signature or key 428 is always the last thing in an RR and so you can always determine 429 its length. 430 ''' 431 self.string = '' 432 if length == None: 433 return 434 435 assert isinstance(length, int) 436 buff = readPrecisely(strio, length) 437 self.string = b64encode(buff) 438 439 def __eq__(self, other): 440 if isinstance(other, Sigstr): 441 return self.string == other.string 442 return False 443 444 def __hash__(self): 445 return hash(self.string) 446 447 def __str__(self): 448 return self.string 449 450 451 class TypeBitmaps(object): 452 ''' 453 bitmap encoding scheme used by NSEC and NSEC3 RR's 454 to indicate the RRset types that exist at the 455 NSEC/NSEC3 RR's original owner name or hashed name. 456 See RFC 4034 and RFC 5155. 457 ''' 458 fmt = 'BB' 459 typeRegex = re.compile('TYPE(\d+)') 460 461 def __init__(self, string=''): 462 self.string = string 463 464 def encode(self, strio, compDict=None): 465 """ 466 Encode the string field, which consists of a set 467 of type names, into an NSEC/NSEC3 type bitmap. 468 469 @type strio: file 470 @param strio: the byte representation of the type bitmap 471 will be written to this file. 472 473 @type compDict: dict 474 @param compDict: not used. 475 """ 476 if not self.string: 477 return; 478 479 #get a sorted list of RR Type Values 480 mnus = self.string.split(' ') 481 mnuVals = [] 482 for mnu in mnus: 483 mnuVal = REV_TYPES.get(mnu, None) 484 if not mnuVal: 485 m = self.typeRegex.match(mnu) 486 if m.groups(): 487 mnuVal = int(m.group(1)) 488 assert mnuVal < 65536 489 else: 490 log.err("can't parse %s in %s" % (mnu, self.string, )) 491 continue; 492 mnuVals.append(mnuVal) 493 mnuVals.sort() 494 495 #convert that to a dict of windows and lists 496 windDict = {} 497 for v in mnuVals: 498 window = (v >> 8) & 0xFF 499 if window not in windDict: 500 windDict[window] = [] 501 windDict[window].append(v & 0xFF) 502 503 #have to sort the keys - they're not in order! 504 windows = windDict.keys() 505 windows.sort() 506 507 #create the bitmaps 508 bmap = bytearray() 509 for w in windows: 510 bmapseg = bytearray(32) 511 maxoff = 0 512 for v in windDict[w]: 513 vm1 = v - 1 514 off = vm1 >> 3 515 bit = vm1 & 0x7 516 msk = 1 << bit 517 bmapseg[off] |= msk 518 maxoff = max(off, maxoff) 519 bmapseg = bmapseg[0:maxoff+1] 520 bmap += chr(w) + chr(maxoff+1) + bmapseg 521 522 strio.write(str(bmap)) 523 524 def decode(self, strio, length=None): 525 """ 526 Decode an NSEC/NSEC3 type bitmap into a string 527 representation of type names. 528 """ 529 self.type_bitmaps = "" 530 if length == None: 531 return 532 533 type_bitmaps = bytearray() 534 l = struct.calcsize(self.fmt) 535 parsed_length = 0 536 while parsed_length < length: 537 buff = readPrecisely(strio, l) 538 wb_num, bm_len = struct.unpack(self.fmt, buff) 539 assert parsed_length + 2 + bm_len <= length 540 bm = readPrecisely(strio, bm_len) 541 byteNum = -1 542 for b in bm: 543 byteNum += 1 544 ob = ord(b) 545 if ob == 0: 546 continue 547 548 for v in range(8): 549 msk = 1<<v 550 if ob & msk: 551 val = wb_num*256 + byteNum*8 + v + 1 552 mnu = QUERY_TYPES.get(val, None) 553 if not mnu: 554 mnu = 'TYPE' + str(val) 555 type_bitmaps += (mnu + ' ') 556 557 parsed_length += 2 + bm_len 558 559 self.type_bitmaps = str(type_bitmaps[0:-1]) 560 561 def __eq__(self, other): 562 if isinstance(other, TypeBitmaps): 563 return self.string == other.string 564 return False 565 566 def __hash__(self): 567 return hash(self.string) 568 569 def __str__(self): 570 return self.string 571 374 572 class Query: 375 573 """ 376 574 Represent a single DNS query. … … 434 632 return 'Query(%r, %r, %r)' % (str(self.name), self.type, self.cls) 435 633 436 634 437 class RRHeader(tputil.FancyEqMixin): 635 636 class OPTHeader(tputil.FancyEqMixin): 438 637 """ 638 A OPT record header. 639 640 @cvar fmt: C{str} specifying the byte format of an OPT Header. 641 642 @ivar name: Root (0, 8-bits) 643 @ivar type: 41 (OPT Record) 644 @ivar payload: An object that implements the IEncodable interface 645 @ivar auth: Whether this header is authoritative or not. 646 """ 647 648 implements(IEncodable) 649 650 compareAttributes = ('name', 'type', 'payload', 'auth') 651 652 fmt = "!H" 653 654 name = None 655 type = None 656 payload = None 657 658 #OPTHeader _really_ has no ttl or rdlength, but the 659 #existence of the attributes is required. 660 ttl = None 661 rdlength = None 662 663 cachedResponse = None 664 665 def __init__(self, payload=None, auth=False): 666 """ 667 @type name: C{str} 668 @param name: Root (0) 669 670 @type type: C{int} 671 @param type: Query type 41. 672 673 @type payload: An object implementing C{IEncodable} 674 @param payload: The OPT payload 675 """ 676 assert (payload is None) or (payload.TYPE == OPT) 677 678 self.name = 0 679 self.type = OPT 680 self.payload = payload 681 self.auth = auth 682 683 def encode(self, strio, compDict=None): 684 strio.write(struct.pack('!B', 0)) 685 strio.write(struct.pack(self.fmt, self.type)) 686 if self.payload: 687 prefix = strio.tell() 688 self.payload.encode(strio, compDict) 689 aft = strio.tell() 690 strio.seek(prefix - 2, 0) 691 strio.write(struct.pack('!H', aft - prefix)) 692 strio.seek(aft, 0) 693 694 def decode(self, strio, length = None): 695 self.name.decode(strio) 696 l = struct.calcsize(self.fmt) 697 buff = readPrecisely(strio, l) 698 r = struct.unpack(self.fmt, buff) 699 self.type = r[0] 700 701 def isAuthoritative(self): 702 return self.auth 703 704 def __str__(self): 705 return '<OPT auth=%s>' % (self.auth and 'True' or 'False') 706 707 @staticmethod 708 def factory(strio, auth=False): 709 ''' 710 reads enough of the stream to figure out if what is there is 711 an OPTHeader or an RRHeader 712 ''' 713 beginPos = strio.tell() 714 name = Name() 715 name.decode(strio) 716 type = struct.unpack(OPTHeader.fmt, readPrecisely(strio, 2))[0] 717 718 if len(name.name) == 0 and type == OPT: 719 return OPTHeader() 720 else: 721 #back up to the beginning and try again 722 strio.seek(beginPos, 0) 723 rrh = RRHeader(auth=auth) 724 rrh.decode(strio) 725 return rrh 726 727 __repr__ = __str__ 728 729 730 class RRHeader(OPTHeader): 731 """ 439 732 A resource record header. 440 733 441 734 @cvar fmt: C{str} specifying the byte format of an RR. … … 445 738 @ivar cls: The query class of the original request. 446 739 @ivar ttl: The time-to-live for this record. 447 740 @ivar payload: An object that implements the IEncodable interface 448 449 @ivar auth: A C{bool} indicating whether this C{RRHeader} was parsed from an 450 authoritative message. 741 @ivar auth: Whether this header is authoritative or not. 451 742 """ 452 743 453 744 implements(IEncodable) … … 1469 1760 return hash(tuple(self.data)) 1470 1761 1471 1762 1763 class Record_OPT(tputil.FancyEqMixin, tputil.FancyStrMixin): 1764 """ 1765 EDNS0 Option record. 1766 1767 @type payload_size: C{int} 1768 @ivar payload_size: Specifies the max UDP Packet size (bytes) that your 1769 network can handle. 1770 1771 @type dnssecOk: C{bool} 1772 @ivar dnssecOk: Requests the server to send DNSSEC RRs and to do DNSSEC 1773 validation (and set the AD bit if the response validates). 1774 1775 @type version: C{int} 1776 @ivar version: The version of DNSSEC used. Currently only version 0 1777 is defined. 1778 """ 1779 implements(IEncodable, IRecord) 1780 TYPE = OPT 1781 fmt = '!HBBHH' 1782 1783 fancybasename = 'OPT' 1784 showAttributes = ('payload_size', ('flags', 'flags', '0x%x'), 'version') 1785 compareAttributes = ('payload_size', 'flags', 'version') 1786 1787 def __init__(self, payload_size=512, dnssecOk=0, version=0, ttl=None): 1788 self.payload_size = payload_size 1789 self.version = version 1790 self.flags = (dnssecOk & 1) << 15 1791 1792 def encode(self, strio, compDict = None): 1793 OPTHeader().encode(strio) 1794 strio.write(struct.pack('!H', self.payload_size)) 1795 strio.write(struct.pack('!B', 0)) # high order 0 1796 strio.write(struct.pack('!B', self.version)) 1797 strio.write(struct.pack('!H', self.flags)) # DO(bit) + Z's 1798 strio.write(struct.pack('!H', 0)) # Data length: 0 1799 1800 def decode(self, strio, length=None): 1801 ''' 1802 are OPT Records always 0 rdlength? 1803 ''' 1804 l = struct.calcsize(self.fmt) 1805 buff = readPrecisely(strio, l) 1806 r = struct.unpack(self.fmt, buff) 1807 self.payload_size, z, self.version, self.flags, length = r 1808 assert length == 0 1809 1810 def __hash__(self): 1811 return hash((self.payload_size, self.version, self.flags)) 1472 1812 1813 class Record_RRSIG(tputil.FancyEqMixin, tputil.FancyStrMixin): 1814 """ 1815 DNSSEC RRSIG record. See RFC 4034 for details. 1816 1817 @type type_covered: C{int} 1818 @ivar type_covered: Identifies the type of the RRset that this RRSIG covers. 1819 1820 @type algo: C{int} 1821 @ivar algo: Identifies the crypto algorithm type used to create the signature. 1822 (5 - RSH/SHA-1 is mandatory. See RFC 4034 App A.1 for the full list.) 1823 1824 @type labels: C{int} 1825 @ivar labels: Specifies the number of labels in the original RRSIG RR owner name. 1826 A validator can use this to determine whether the answer was synthesized from 1827 a wildcard. 1828 1829 @type original_ttl: C{int} 1830 @ivar original_ttl: Specifies the TTL of the covered RRset as it appears in the 1831 authoritative zone. 1832 1833 @type sig_expiration: C{int} 1834 @ivar sig_expiration: This RRSIG must NOT be used after this time. Seconds 1835 since 1/1/1970, Modulo 2**32, compare using DNS Serial Number Arithmetic 1836 1837 @type sig_inception: C{int} 1838 @ivar sig_inception: This RRSIG must NOT be used prior to this time. Seconds 1839 since 1/1/1970, Modulo 2**32, compare using DNS Serial Number Arithmetic 1840 1841 @type key_tag: C{int} 1842 @ivar key_tag: Contains the key tag value of the DNSKEY RR that validates this 1843 signature, in network byte order. See RFC 4034 App B. 1844 1845 @type signers_name: L{Name} 1846 @ivar signers_name: Identifies the owner name of the DNSKEY RR that a validator 1847 should use to validate this signature. Must not use DNS name compression. 1848 1849 @type signature: L{Sigstr} 1850 @ivar signature: Contains the cryptographic signature that covers the RRSIG 1851 RDATA (excluding the Signature field and the RRset specified by the RRSIG 1852 owner name, RRSIG class and RRSIG Type Covered fields. 1853 1854 @type ttl: C{int} 1855 @ivar ttl: The maximum number of seconds which this record should be 1856 cached. 1857 """ 1858 implements(IEncodable, IRecord) 1859 TYPE = RRSIG 1860 fmt = '!HBBIIIH' 1861 1862 fancybasename = 'RRSIG' 1863 showAttributes = ('type_covered', 'algo', 'labels', 'original_ttl', 1864 ('_sig_expiration', 'sig_expiration', '%s'), 1865 ('_sig_inception', 'sig_inception', '%s'), 1866 'key_tag', 1867 ('signers_name', 'signers_name', '%s'), 1868 ('_signature', 'signature', '%s'), 'ttl') 1869 compareAttributes = ('type_covered', 'algo', 'labels', 'original_ttl', 1870 'sig_expiration', 'sig_inception', 'key_tag', 1871 'signers_name', 'signature', 'ttl') 1872 1873 _sig_expiration = property(lambda self: str(self.sig_expiration)) 1874 _sig_inception = property(lambda self: str(self.sig_inception)) 1875 _signature = property(lambda self: self.signature.string) 1876 1877 def __init__(self, type_covered=A, algo=0, labels=0, original_ttl=0, 1878 sig_expiration='', sig_inception='', key_tag=0, 1879 signers_name='', signature='', ttl=None): 1880 self.type_covered = type_covered 1881 self.algo = algo 1882 self.labels = labels 1883 self.original_ttl = original_ttl 1884 self.sig_expiration = DateSNA(sig_expiration) 1885 self.sig_inception = DateSNA(sig_inception) 1886 self.key_tag = key_tag 1887 self.signers_name = Name(signers_name) 1888 self.signature = Sigstr(signature) 1889 self.ttl = str2time(ttl) 1890 1891 def encode(self, strio, compDict = None): 1892 strio.write(struct.pack(self.fmt, 1893 self.type_covered, 1894 self.algo, 1895 self.labels, 1896 self.original_ttl, 1897 self.sig_expiration.asInt(), 1898 self.sig_inception.asInt(), 1899 self.key_tag)) 1900 self.signers_name.encode(strio, None) 1901 self.signature.encode(strio, compDict) 1902 1903 def decode(self, strio, length=None): 1904 start = strio.tell() 1905 l = struct.calcsize(self.fmt) 1906 buff = readPrecisely(strio, l) 1907 r = struct.unpack(self.fmt, buff) 1908 self.type_covered, self.algo, self.labels, self.original_ttl, \ 1909 sig_expiration, sig_inception, self.key_tag = r 1910 self.sig_expiration = DateSNA.fromInt(sig_expiration) 1911 self.sig_inception = DateSNA.fromInt(sig_inception) 1912 self.signers_name.decode(strio) 1913 here = strio.tell() 1914 self.signature.decode(strio, length + start - here if length else None) 1915 1916 def __hash__(self): 1917 return hash((self.type_covered, self.algo, self.labels, self.original_ttl, 1918 self.sig_expiration, self.sig_inception, self.key_tag, 1919 self.signers_name, self.signature)) 1920 1921 class Record_DS(tputil.FancyEqMixin, tputil.FancyStrMixin): 1922 """ 1923 A DNSSEC DS record. 1924 1925 @type key_tag: C{int} 1926 @ivar key_tag: Lists the key tag of the DNSKEY RR referred to by this DS record. 1927 1928 @type algo: C{int} 1929 @ivar algo: Lists the algorithm number of the DNSKEY RR referenced by this DS record. 1930 1931 @type digest_type: C{int} 1932 @ivar digest_type: Identifies the algorithm used to construct the digest field. 1933 1934 @type digest: L{Sigstr} 1935 @ivar digest: Contains a digest of the refeerenced DNSKEY RR calculated by the 1936 algorithm identified by the digest_type field. 1937 1938 @type ttl: C{int} 1939 @ivar ttl: The maximum number of seconds which this record should be 1940 cached. 1941 """ 1942 implements(IEncodable, IRecord) 1943 TYPE = DS 1944 fmt = '!HBB' 1945 1946 fancybasename = 'DS' 1947 showAttributes = ('key_tag', 'algo', 'digest_type', ('_digest', 'digest', '%s'), 'ttl') 1948 compareAttributes = ('key_tag', 'algo', 'digest_type', 'digest', 'ttl') 1949 1950 _digest = property(lambda self: self.digest.string) 1951 1952 def __init__(self, key_tag=0, algo=0, digest_type=0, digest='', ttl=None): 1953 self.key_tag = key_tag 1954 self.algo = algo 1955 self.digest_type = digest_type 1956 self.digest = Sigstr(digest) 1957 self.ttl = str2time(ttl) 1958 1959 def encode(self, strio, compDict = None): 1960 strio.write(struct.pack(self.fmt, 1961 self.key_tag, 1962 self.algo, 1963 self.digest_type)) 1964 self.digest.encode(strio, None) 1965 1966 def decode(self, strio, length=None): 1967 start = strio.tell() 1968 l = struct.calcsize(self.fmt) 1969 buff = readPrecisely(strio, l) 1970 r = struct.unpack(self.fmt, buff) 1971 self.key_tag, self.algo, self.digest_type = r 1972 here = strio.tell() 1973 self.digest.decode(strio, length + start - here if length else None) 1974 1975 def __hash__(self): 1976 return hash((self.key_tag, self.algo, self.digest_type, self.digest)) 1977 1978 class Record_DNSKEY(tputil.FancyEqMixin, tputil.FancyStrMixin): 1979 """ 1980 A DNSSEC DNSKEY record. Holds the public key for a signed RRset. 1981 1982 @type flags: C{int} 1983 @ivar flags: Bit 7 is the Zone Key flag. If bit 7 has value 1, then the 1984 DNSKEY record holds a DNS zone key and the DNSKEY RR's owner name is 1985 the name of a zone. If bit 7 has value 0, then the DNSKEY record 1986 holds some other type of DNS public key and MUST NOT be used to 1987 verify RRSIGs that cover RRsets. 1988 Bit 15 is the Secure Entry Point flag. See RFC 3757.) 1989 All other bits are reserved and must be zero. 1990 1991 @type protocol: C{int} 1992 @ivar protocol: Must have value 3. The DNSKEY RR must be treated as invalid 1993 if this field does not contain 3. 1994 1995 @type algo: C{int} 1996 @ivar algo: Identifies the public key's cryptographic algorithm and determines 1997 the format of the pub_key field. See RFC 4034 App A. 1998 1999 @type pub_key: L{Sigstr} 2000 @ivar pub_key: Holds the public key material. 2001 2002 @type ttl: C{int} 2003 @ivar ttl: The maximum number of seconds which this record should be 2004 cached. 2005 """ 2006 implements(IEncodable, IRecord) 2007 TYPE = DNSKEY 2008 fmt = '!HBB' 2009 2010 fancybasename = 'DNSKEY' 2011 showAttributes = ('flags', 'protocol', 'algo', ('_pub_key', 'pub_key', '%s'), 'ttl') 2012 compareAttributes = ('flags', 'protocol', 'algo', 'pub_key', 'ttl') 2013 2014 _pub_key = property(lambda self: self.pub_key.string) 2015 2016 def __init__(self, flags=0, protocol=0, algo=0, pub_key='', ttl=None): 2017 self.flags = flags 2018 self.protocol = protocol 2019 self.algo = algo 2020 self.pub_key = Sigstr(pub_key) 2021 self.ttl = str2time(ttl) 2022 2023 def encode(self, strio, compDict = None): 2024 strio.write(struct.pack(self.fmt, 2025 self.flags, 2026 self.protocol, 2027 self.algo)) 2028 self.pub_key.encode(strio, None) 2029 2030 def decode(self, strio, length=None): 2031 start = strio.tell() 2032 l = struct.calcsize(self.fmt) 2033 buff = readPrecisely(strio, l) 2034 r = struct.unpack(self.fmt, buff) 2035 self.flags, self.protocol, self.algo = r 2036 here = strio.tell() 2037 self.pub_key.decode(strio, length + start - here if length else None) 2038 2039 def __hash__(self): 2040 return hash((self.flags, self.protocol, self.algo, self.pub_key)) 2041 2042 class Record_NSEC(tputil.FancyEqMixin, tputil.FancyStrMixin): 2043 """ 2044 A DNSSEC NSEC record provides authenticated denial of existance for DNS data. 2045 2046 A DNSSEC NSEC record lists: 2047 2048 1) the next owner name in canonical ordering of the zone that contains authoritataive 2049 data or a delegation point NS RRset. 2050 2051 2) the set of RR types present at the NSEC RR's owner name. 2052 2053 @type nxt_name: L{Name} 2054 @ivar nxt_name: The next owner name that has authoritative data or contains a 2055 delegation point NS RRset. 2056 2057 @type type_bitmaps: L{TypeBitmaps} 2058 @ivar type_bitmaps: Identifies the RRset types that exist at the NSEC RR's owner name. 2059 2060 @type ttl: C{int} 2061 @ivar ttl: The maximum number of seconds which this record should be 2062 cached. 2063 """ 2064 implements(IEncodable, IRecord) 2065 TYPE = NSEC 2066 2067 fancybasename = 'NSEC' 2068 showAttributes = (('nxt_name', 'nxt_name', '%s'), ('_type_bitmaps', 'type_bitmaps', '%s'), 'ttl') 2069 compareAttributes = ('nxt_name', 'type_bitmaps', 'ttl') 2070 2071 _type_bitmaps = property(lambda self: self.type_bitmaps.string) 2072 2073 def __init__(self, nxt_name='', type_bitmaps=None, ttl=None): 2074 self.nxt_name = Name(nxt_name) 2075 self.type_bitmaps = TypeBitmaps(type_bitmaps) 2076 self.ttl = str2time(ttl) 2077 2078 def encode(self, strio, compDict = None): 2079 self.nxt_name.encode(strio, None) 2080 self.type_bitmaps.encode(strio, None) 2081 2082 def decode(self, strio, length=None): 2083 start = strio.tell() 2084 self.nxt_name.decode(strio, None) 2085 here = strio.tell() 2086 self.type_bitmaps.decode(strio, length + start - here if length else None) 2087 2088 def __hash__(self): 2089 return hash((self.nxt_name, self.type_bitmaps)) 2090 2091 class Record_NSEC3PARAM(tputil.FancyEqMixin, tputil.FancyStrMixin): 2092 """ 2093 A DNSSEC NSEC3PARAM record contains the NSEC3 parameters (hash algorithm, 2094 flags, iterations and salt) needed by authoritative servers to calculate 2095 hashed owner names. The presence of an NSEC3PARAM RR at a zone apex 2096 indicates that the specified parameters may be used by authoritative 2097 servers to choose an appropriate set of NSEC3 RRs for negative responses. 2098 2099 @type hash_algo: C{int} 2100 @ivar hash_algo: Identifies the cryptographic hash algorithm used to construct the hash value. 2101 2102 @type flags: C{int} 2103 @ivar flags: Identifies 8 1-bit flags. The only flag presently defined is the 2104 opt-out flag. If the opt-out flag is set, the NSEC3 record covers zero or more unsigned 2105 delegations. If the opt-out flag is clear, the NSEC3 record covers zero unsigned delegations. 2106 2107 @type iterations: C{int} 2108 @ivar iterations: Defines the nubmer of additional times the hash algorithm has been performed. 2109 2110 @type salt: L{Charset} 2111 @ivar salt: Identifies the salt value provided to the hash. 2112 2113 @type ttl: C{int} 2114 @ivar ttl: The maximum number of seconds which this record should be 2115 cached. 2116 """ 2117 implements(IEncodable, IRecord) 2118 TYPE = NSEC3 2119 fmt = '!BBH' 2120 2121 fancybasename = 'NSEC3' 2122 showAttributes = ('hash_algo', 'flags', 'iterations', ('_salt', 'salt', '%s'), 'ttl') 2123 compareAttributes = ('hash_algo', 'flags', 'iterations', 'salt', 'ttl') 2124 2125 _salt = property(lambda self: self.salt.string) 2126 2127 def __init__(self, hash_algo=0, flags=0, iterations=0, salt='', ttl=None): 2128 self.hash_algo = hash_algo 2129 self.flags = flags 2130 self.iterations = iterations 2131 self.salt = Charstr(salt) 2132 self.ttl = str2time(ttl) 2133 2134 def encode(self, strio, compDict = None): 2135 strio.write(struct.pack(self.fmt, 2136 self.hash_algo, 2137 self.flags, 2138 self.iterations)) 2139 self.salt.encode(strio, None) 2140 2141 def decode(self, strio, length=None): 2142 start = strio.tell() 2143 l = struct.calcsize(self.fmt) 2144 buff = readPrecisely(strio, l) 2145 r = struct.unpack(self.fmt, buff) 2146 self.hash_algo, self.flags, self.iterations = r 2147 self.salt.decode(strio) 2148 here = strio.tell() 2149 2150 def __hash__(self): 2151 return hash((self.hash_algo, self.flags, self.iterations, self.salt)) 2152 2153 class Record_NSEC3(Record_NSEC3PARAM): 2154 """ 2155 A DNSSEC NSEC3 record provides non-zone-enumerable authenticated denial of existance 2156 for DNS data and permits a gradual expansion of delegation-centric zones. 2157 2158 A DNSSEC NSEC3 record lists: 2159 2160 1) the set of RR types present at the original owner name of the NSEC RR. 2161 2162 2) the next hashed owner name in the hash order of the zone. 2163 2164 @type hash_algo: C{int} 2165 @ivar hash_algo: Identifies the cryptographic hash algorithm used to construct the hash value. 2166 2167 @type flags: C{int} 2168 @ivar flags: Identifies 8 1-bit flags. The only flag presently defined is the 2169 opt-out flag. If the opt-out flag is set, the NSEC3 record covers zero or more unsigned 2170 delegations. If the opt-out flag is clear, the NSEC3 record covers zero unsigned delegations. 2171 2172 @type iterations: C{int} 2173 @ivar iterations: Defines the nubmer of additional times the hash algorithm has been performed. 2174 2175 @type salt: L{Charset} 2176 @ivar salt: Identifies the salt value provided to the hash. 2177 2178 @type nxt_hash_owner_name: L{Charset} 2179 @ivar nxt_hash_owner_name: Contains the next hashed owner name in the zone in hash order. 2180 2181 @type type_bitmaps: L{TypeBitmaps} 2182 @ivar type_bitmaps: Identifies the RRset types that exist at the NSEC3 RR's original owner name. 2183 2184 @type ttl: C{int} 2185 @ivar ttl: The maximum number of seconds which this record should be 2186 cached. 2187 """ 2188 implements(IEncodable, IRecord) 2189 TYPE = NSEC3 2190 fmt = '!BBH' 2191 2192 fancybasename = 'NSEC3' 2193 showAttributes = ('hash_algo', 'flags', 'iterations', ('_salt', 'salt', '%s'), ('nxt_hash_owner_name', 'nxt_hash_owner_name', '%s'), ('_type_bitmaps', 'type_bitmaps', '%s'), 'ttl') 2194 compareAttributes = ('hash_algo', 'flags', 'iterations', 'salt', 'nxt_hash_owner_name', 'type_bitmaps', 'ttl') 2195 2196 _salt = property(lambda self: self.salt.string) 2197 _type_bitmaps = property(lambda self: self.type_bitmaps.string) 2198 2199 def __init__(self, hash_algo=0, flags=0, iterations=0, salt='', nxt_hash_owner='', type_bitmaps=None, ttl=None): 2200 Record_NSEC3PARAM.__init__( self, hash_algo, flags, iterations, salt, ttl) 2201 self.nxt_hash_owner_name = Charstr(nxt_hash_owner) 2202 self.type_bitmaps = TypeBitmaps(type_bitmaps) 2203 2204 def encode(self, strio, compDict = None): 2205 Record_NSEC3PARAM.encode(self, strio, compDict) 2206 self.nxt_hash_owner_name.encode(strio, None) 2207 self.type_bitmaps.encode(strio, None) 2208 2209 def decode(self, strio, length=None): 2210 start = strio.tell() 2211 Record_NSEC3PARAM.decode(self, strio, compDict) 2212 self.nxt_hash_owner_name.decode(strio) 2213 here = strio.tell() 2214 self.type_bitmaps.decode(strio, length + start - here if length else None) 2215 2216 def __hash__(self): 2217 return hash((self.hash_algo, self.flags, self.iterations, self.salt, 2218 self.nxt_hash_owner_name, self.type_bitmaps)) 2219 1473 2220 # This is a fallback record 1474 2221 class UnknownRecord(tputil.FancyEqMixin, tputil.FancyStrMixin, object): 1475 2222 """ … … 1546 2293 queries = answers = add = ns = None 1547 2294 1548 2295 def __init__(self, id=0, answer=0, opCode=0, recDes=0, recAv=0, 1549 auth=0, rCode=OK, trunc=0, maxSize=512):2296 auth=0, rCode=OK, trunc=0, maxSize=512, authData=0, chkDis=0): 1550 2297 self.maxSize = maxSize 1551 2298 self.id = id 1552 2299 self.answer = answer 1553 2300 self.opCode = opCode 1554 self.auth = auth 1555 self.trunc = trunc 1556 self.recDes = recDes 1557 self.recAv = recAv 2301 self.auth = auth #AA - Authoritative Answer 2302 self.trunc = trunc #TC - TrunCated 2303 self.recDes = recDes #RD - Recursion Desired 2304 self.recAv = recAv #RA - Recursion Available 2305 self.authData = authData #AD - Authentic Data 2306 self.chkDis = chkDis #CD - Checking Disabled 1558 2307 self.rCode = rCode 1559 2308 self.queries = [] 1560 2309 self.answers = [] … … 1599 2348 | ((self.auth & 1 ) << 2 ) 1600 2349 | ((self.trunc & 1 ) << 1 ) 1601 2350 | ( self.recDes & 1 ) ) 1602 byte4 = ( ( (self.recAv & 1 ) << 7 ) 2351 byte4 = ( ((self.recAv & 1 ) << 7 ) 2352 |((self.authData & 1 ) << 5 ) 2353 |((self.chkDis & 1 ) << 4 ) 1603 2354 | (self.rCode & 0xf ) ) 1604 2355 1605 2356 strio.write(struct.pack(self.headerFmt, self.id, byte3, byte4, … … 1619 2370 self.trunc = ( byte3 >> 1 ) & 1 1620 2371 self.recDes = byte3 & 1 1621 2372 self.recAv = ( byte4 >> 7 ) & 1 2373 self.authData = ( byte4 >> 5 ) & 1 2374 self.chkDis = ( byte4 >> 4 ) & 1 1622 2375 self.rCode = byte4 & 0xf 1623 2376 1624 2377 self.queries = [] … … 1637 2390 1638 2391 def parseRecords(self, list, num, strio): 1639 2392 for i in range(num): 1640 header = RRHeader(auth=self.auth)1641 2393 try: 1642 header .decode(strio)2394 header = OPTHeader.factory(strio, auth=self.auth) 1643 2395 except EOFError: 1644 2396 return 1645 2397 t = self.lookupRecordType(header.type) … … 1749 2501 query, or errbacked with any errors that could happen (exceptions 1750 2502 during writing of the query, timeout errors, ...). 1751 2503 """ 1752 m = Message(id, recDes=1) 2504 chkDis=self.controller.dnssecConfig.chkDis 2505 m = Message(id, recDes=self.controller.dnssecConfig.recDes, chkDis=chkDis) 1753 2506 m.queries = queries 2507 if self.controller.dnssecConfig.ednsEnabled: 2508 m.additional = [Record_OPT(payload_size = self.controller.dnssecConfig.maxUdpPktSz, 2509 version = self.controller.dnssecConfig.version, 2510 dnssecOk = self.controller.dnssecConfig.dnssecOk)] 1754 2511 1755 2512 try: 1756 2513 writeMessage(m) … … 1804 2561 self.transport.write(message.toStr(), address) 1805 2562 1806 2563 def startListening(self): 1807 self._reactor.listenUDP(0, self, maxPacketSize=512) 2564 maxPacketSize = 512 2565 if self.controller.dnssecConfig.ednsEnabled: 2566 maxPacketSize = self.controller.dnssecConfig.maxUdpPktSz 2567 self._reactor.listenUDP(0, self, maxPacketSize=maxPacketSize) 1808 2568 1809 2569 def datagramReceived(self, data, addr): 1810 2570 """ -
names/secondary.py
90 90 91 91 @ivar _reactor: The reactor to use to perform the zone transfers, or C{None} 92 92 to use the global reactor. 93 94 #ivar dnssecConfig a L{DnssecConfig} giving the DNSSEC configuration to set 95 on the resolver. 93 96 """ 94 97 95 98 transferring = False … … 97 100 _port = 53 98 101 _reactor = None 99 102 100 def __init__(self, primaryIP, domain ):101 common.ResolverBase.__init__(self )103 def __init__(self, primaryIP, domain, dnssecConfig=None): 104 common.ResolverBase.__init__(self, dnssecConfig) 102 105 self.primary = primaryIP 103 106 self.domain = domain 104 107 -
names/ser_num_arith.py
1 # -*- test-case-name: twisted.names.test.test_ser_num_arith -*- 2 # Copyright (c) Twisted Matrix Laboratories. 3 # See LICENSE for details. 4 5 """ 6 Serial Number Arithmetic 7 8 This module implements RFC 1982 DNS Serial Number Arithmetic 9 (see http://tools.ietf.org/pdf/rfc1982.pdf). 10 SNA is used in DNS and specifically in DNSSEC as defined in 11 RFC 4034 in the DNSSEC Signature Expiration and Inception Fields. 12 13 bob.novas@shinkuro.com 14 """ 15 16 import calendar, time 17 18 class SNA(object): 19 """ 20 implements RFC 1982 - DNS Serial Number Arithmetic 21 """ 22 SERIAL_BITS = 32 23 MODULOVAL = 2**SERIAL_BITS 24 HLFRNG = 2**(SERIAL_BITS-1) 25 MAXADD = (2**(SERIAL_BITS-1)-1) 26 27 def __init__(self, number): 28 self._number = int(number)%self.MODULOVAL 29 30 def __repr__(self): 31 return str(self._number) 32 33 def asInt(self): 34 return self._number 35 36 def eq(self, sna2): 37 assert isinstance(sna2, SNA) 38 return sna2._number == self._number 39 40 def lt(self, sna2): 41 assert isinstance(sna2, SNA) 42 return not self.eq(sna2) and \ 43 ((self._number < sna2._number) and ((sna2._number - self._number) < self.HLFRNG) or \ 44 (self._number > sna2._number) and ((self._number - sna2._number) > self.HLFRNG)) 45 46 def gt(self, sna2): 47 assert isinstance(sna2, SNA) 48 return not self.eq(sna2) and \ 49 ((self._number < sna2._number) and ((sna2._number - self._number) > self.HLFRNG) or \ 50 (self._number > sna2._number) and ((self._number - sna2._number) < self.HLFRNG)) 51 52 def le(self, sna2): 53 return self.eq(sna2) or self.lt(sna2) 54 55 def ge(self, sna2): 56 return self.eq(sna2) or self.gt(sna2) 57 58 def add(self, sna2): 59 assert isinstance(sna2, SNA) 60 if sna2.le(SNA(self.MAXADD)): 61 return SNA( (self._number + sna2._number)%self.MODULOVAL ) 62 else: 63 raise ArithmeticError 64 65 def __hash__(self): 66 return hash(self._number) 67 68 __eq__ = eq 69 __lt__ = lt 70 __gt__ = gt 71 __le__ = le 72 __ge__ = ge 73 __add__ = add 74 75 @staticmethod 76 def max(snaList): 77 """ 78 this takes a list of sna's from which it will pick the sn with the highest value 79 """ 80 if len(snaList) == 0: 81 return None 82 trialMax = snaList[0] 83 for s in snaList[1:]: 84 if not trialMax: 85 trialMax = s 86 elif s and s > trialMax: 87 trialMax = s 88 return trialMax 89 90 class DateSNA(SNA): 91 """ 92 implements DNS Serial Number Arithmetic 93 for dates 'YYYYMMDDHHMMSS' per RFC 4034 P3.1.5 94 """ 95 fmt = '%Y%m%d%H%M%S' 96 97 def __init__(self, utcDateTime=''): 98 ''' 99 accept a UTC date/time string as YYMMDDHHMMSS 100 and convert it to seconds since the epoch 101 ''' 102 if not utcDateTime: 103 utcDateTime = '19700101000000' 104 dtstruct = time.strptime(utcDateTime, DateSNA.fmt) 105 assert dtstruct.tm_year < 1970+136 106 secondsSinceE = calendar.timegm(dtstruct) 107 super(DateSNA, self).__init__(secondsSinceE) 108 109 def add(self, sna2): 110 if not isinstance(sna2, SNA): 111 return NotImplemented 112 113 if sna2.le(SNA(self.MAXADD)) and (self._number + sna2._number < self.MODULOVAL): 114 sna = SNA((self._number + sna2._number)%self.MODULOVAL) 115 return DateSNA.fromSNA(sna) 116 else: 117 raise ArithmeticError 118 119 def asDate(self): 120 dtstruct = time.gmtime(self._number) 121 return time.strftime(DateSNA.fmt, dtstruct) 122 123 @staticmethod 124 def fromSNA(sna): 125 assert isinstance(sna, SNA) 126 d = DateSNA() 127 d._number = sna._number 128 return d 129 130 @staticmethod 131 def fromInt(i): 132 return DateSNA.fromSNA(SNA(i)) 133 134 def __str__(self): 135 return self.asDate() 136 -
names/test/test_client.py
8 8 from twisted.names import client, dns 9 9 from twisted.names.error import DNSQueryTimeoutError 10 10 from twisted.trial import unittest 11 from twisted.names.common import ResolverBase 11 from twisted.names.common import ResolverBase, DnssecConfig 12 from twisted.names.dns import Query, Message 12 13 from twisted.internet import defer, error 13 14 from twisted.python import failure 14 15 from twisted.python.deprecate import getWarningMethod, setWarningMethod 15 16 from twisted.python.compat import set 17 from twisted.names.test.test_rootresolve import MemoryReactor 16 18 17 19 18 20 class FakeResolver(ResolverBase): … … 428 430 # Disconnecting should remove the protocol from the connection list: 429 431 protocol.connectionLost(None) 430 432 self.assertNotIn(protocol, resolver.connections) 433 434 435 def _edns0ConfigurationTest(self, reactor, resolver): 436 """ 437 A Resolver created with edns0 sends an OPT record as part of the 438 query indicating the maxUdpPktSz and EDNS version supported 439 (only EDNS version 0 - the default - is defined by spec). 440 441 In addition, check that the message flag bits (DO, CD, RC) agree 442 with the flags set in the resolver. 443 """ 444 #make sure EDNS is enabled 445 self.assertTrue(resolver.dnssecConfig.ednsEnabled) 446 447 d = resolver._query(('example.com', 53), 448 [Query('foo.example.com',dns.A, dns.IN)], 449 30) 450 451 # A UDP port should have been started 452 portNumber, transport = reactor.udpPorts.popitem() 453 454 # and a DNS packet sent 455 [(packet, address)] = transport._sentPackets 456 457 msg = Message() 458 msg.fromStr(packet) 459 460 # the query should have an additional OPT Header with 461 # version == 0 and payload_size as defined by the resolver's dnssecConfig 462 # and DO should be set 463 self.assertEqual(len(msg.additional), 1) 464 additional = msg.additional[0] 465 self.assertEqual(additional.type, dns.OPT) 466 self.assertEqual(additional.payload.version, resolver.dnssecConfig.version) 467 self.assertEqual(additional.payload.payload_size, resolver.dnssecConfig.maxUdpPktSz) 468 #payload.flags bit 15 is DO, should equal resolver.dnssecOk's truth value 469 self.assertEqual(not not(additional.payload.flags & 0x8000), resolver.dnssecConfig.dnssecOk) 470 471 # the rest of the query should be as above also 472 self.assertEqual(msg.queries, [Query('foo.example.com', dns.A, dns.IN)]) 473 self.assertEqual(msg.answers, []) 474 self.assertEqual(msg.authority, []) 431 475 476 # the message header flags should be set as per the resolver's dnssecConfig settings 477 self.assertEqual(msg.chkDis, resolver.dnssecConfig.chkDis) 478 self.assertEqual(msg.recDes, resolver.dnssecConfig.recDes) 479 480 response = [] 481 d.addCallback(response.append) 482 self.assertEqual(response, []) 483 484 # Once a reply is received, the Deferred should fire. 485 # Make the flag bits in the message agree with what you asked for 486 del msg.queries[:] 487 msg.answer = 1 488 msg.answers.append(dns.RRHeader('foo.example.com', payload=dns.Record_A('5.8.13.21'))) 489 msg.authData = resolver.dnssecConfig.dnssecOk #if you requested DO, say you got AD 490 msg.chkDis = resolver.dnssecConfig.chkDis 491 msg.recDes = resolver.dnssecConfig.recDes 492 transport._protocol.datagramReceived(msg.toStr(), ('1.1.2.4', 1053)) 493 return response[0] 432 494 495 496 def test_dnssecEnabled(self): 497 """ 498 A query sent with DNSSEC Enabled has an additional OPT record with 499 DO set. Such a query returns a 4-tuple as a result, with the 4th 500 member of the tuple being the message with the header bits set as 501 set in the original query. 502 """ 503 # Create a resolver with EDNS0, max packet size = 4096, 504 # and dnssecOk, chkDis and recDes = True 505 maxPacketSize = 4096 506 dsc = DnssecConfig(ednsEnabled=True, 507 maxUdpPktSz=maxPacketSize, 508 dnssecOk=True, # DO 509 chkDis=True, # CD 510 recDes=True) # RC 433 511 512 reactor = MemoryReactor() 513 resolver = client.Resolver(servers=[('example.com', 53)], 514 reactor=reactor, 515 dnssecConfig=dsc) 516 517 message = self._edns0ConfigurationTest(reactor, resolver) 518 519 #check that a resolver with dnssecOk returns a 4-tuple with the header set as in the query 520 answer, authority, additional, message = resolver.filterAnswers(message) 521 self.assertEqual(answer, 522 [dns.RRHeader('foo.example.com', payload=dns.Record_A('5.8.13.21', ttl=0))]) 523 self.assertEqual(authority, []) 524 self.assertEqual(additional, []) 525 self.assertIsInstance(message, dns.Message) 526 self.assertTrue(message.authData) 527 self.assertTrue(message.chkDis) 528 self.assertTrue(message.recDes) 529 530 531 def test_dnssecDisabled(self): 532 """ 533 A query sent with DNSSEC Disabled but EDNS enabled has an additional 534 OPT record with DO clear. Such a query returns a 3-tuple as a result. 535 """ 536 537 # Create a resolver with EDNS0, max packet size = 4096, 538 # and dnssecOk = False, but recDes = True 539 maxPacketSize = 4096 540 dsc = DnssecConfig(ednsEnabled=True, 541 maxUdpPktSz=maxPacketSize, 542 dnssecOk=False, # not DO 543 recDes=True) # RC 544 545 reactor = MemoryReactor() 546 resolver = client.Resolver(servers=[('example.com', 53)], 547 reactor=reactor, 548 dnssecConfig=dsc) 549 550 message = self._edns0ConfigurationTest(reactor, resolver) 551 552 #check that a resolver with dnssecOk == False returns a 3-tuple 553 #containing the right stuff. Note - no access to header info in this case 554 answer, authority, additional = resolver.filterAnswers(message) 555 self.assertEqual(answer, 556 [dns.RRHeader('foo.example.com', payload=dns.Record_A('5.8.13.21', ttl=0))]) 557 self.assertEqual(authority, []) 558 self.assertEqual(additional, []) 559 560 434 561 class ClientTestCase(unittest.TestCase): 435 562 436 563 def setUp(self): … … 658 785 return d 659 786 660 787 788 def test_lookupDNSKey(self): 789 """ 790 See L{test_lookupAddress} 791 """ 792 d = client.lookupDNSKey(self.hostname) 793 d.addCallback(self.checkResult, dns.DNSKEY) 794 return d 795 796 797 def test_lookupDS(self): 798 """ 799 See L{test_lookupAddress} 800 """ 801 d = client.lookupDS(self.hostname) 802 d.addCallback(self.checkResult, dns.DS) 803 return d 804 805 806 def test_lookupNSEC(self): 807 """ 808 See L{test_lookupAddress} 809 """ 810 d = client.lookupNSEC(self.hostname) 811 d.addCallback(self.checkResult, dns.NSEC) 812 return d 813 814 815 def test_lookupNSEC3(self): 816 """ 817 See L{test_lookupAddress} 818 """ 819 d = client.lookupNSEC3(self.hostname) 820 d.addCallback(self.checkResult, dns.NSEC3) 821 return d 822 823 824 def test_lookupNSEC3Param(self): 825 """ 826 See L{test_lookupAddress} 827 """ 828 d = client.lookupNSEC3Param(self.hostname) 829 d.addCallback(self.checkResult, dns.NSEC3PARAM) 830 return d 831 832 833 def test_lookupRRSIG(self): 834 """ 835 See L{test_lookupAddress} 836 """ 837 d = client.lookupRRSIG(self.hostname) 838 d.addCallback(self.checkResult, dns.RRSIG) 839 return d 840 841 661 842 class ThreadedResolverTests(unittest.TestCase): 662 843 """ 663 844 Tests for L{client.ThreadedResolver}. -
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 -
names/test/test_names.py
98 98 '\x12\x01\x16\xfe\xc1\x00\x01'), 99 99 dns.Record_NAPTR(100, 10, "u", "sip+E2U", 100 100 "!^.*$!sip:information@domain.tld!"), 101 dns.Record_AAAA('AF43:5634:1294:AFCB:56AC:48EF:34C3:01FF')], 101 dns.Record_AAAA('AF43:5634:1294:AFCB:56AC:48EF:34C3:01FF'), 102 dns.Record_DNSKEY(0x10, 3, 5, 103 "M+u8Uxm2y2Q142qED0kVNIiSOHBkfiU3xBhMq9H4T/K+oeC7Y81HIOFEh9k6ZS/Ba5X0/Fr1yyq5Z/+0/Q845Kya8Lmkp/ikJVe/9id2TC2hoffpZ9pbZRjIeBTAvdTboGmGuqG/ljnDLJrJpoF6g8g6fHR9eekIWis8LJ55Y1k=" 104 )], 102 105 'http.tcp.test-domain.com': [ 103 106 dns.Record_SRV(257, 16383, 43690, 'some.other.place.fool') 104 107 ], 105 108 'host.test-domain.com': [ 106 109 dns.Record_A('123.242.1.5'), 107 110 dns.Record_A('0.255.0.255'), 111 dns.Record_RRSIG(dns.A, 5, 3, 86400, '20120101000000', '20120201000000', 2642, 'test-domain.com', 112 "M+u8Uxm2y2Q142qED0kVNIiSOHBkfiU3xBhMq9H4T/K+oeC7Y81HIOFEh9k6ZS/Ba5X0/Fr1yyq5Z/+0/Q845Kya8Lmkp/ikJVe/9id2TC2hoffpZ9pbZRjIeBTAvdTboGmGuqG/ljnDLJrJpoF6g8g6fHR9eekIWis8LJ55Y1k=") 108 113 ], 109 114 'host-two.test-domain.com': [ 110 115 # … … 434 439 [dns.Record_NAPTR(100, 10, "u", "sip+E2U", 435 440 "!^.*$!sip:information@domain.tld!", 436 441 ttl=19283784)]) 442 443 def test_DNSKEY(self): 444 """Test DNS 'DNSKEY' record queries.""" 445 return self.namesTest( 446 self.resolver.lookupDNSKey('test-domain.com'), 447 [dns.Record_DNSKEY(0x10, 3, 5, 448 "M+u8Uxm2y2Q142qED0kVNIiSOHBkfiU3xBhMq9H4T/K+oeC7Y81HIOFEh9k6ZS/Ba5X0/Fr1yyq5Z/+0/Q845Kya8Lmkp/ikJVe/9id2TC2hoffpZ9pbZRjIeBTAvdTboGmGuqG/ljnDLJrJpoF6g8g6fHR9eekIWis8LJ55Y1k=", 449 ttl=19283784)]) 437 450 438 439 440 451 class DNSServerFactoryTests(unittest.TestCase): 441 452 """ 442 453 Tests for L{server.DNSServerFactory}. … … 890 901 self.assertEqual(service.domains[1].domain, 'example.edu') 891 902 892 903 893 894 904 class SecondaryAuthorityTests(unittest.TestCase): 895 905 """ 896 906 L{twisted.names.secondary.SecondaryAuthority} correctly constructs objects -
names/test/test_ser_num_arith.py
1 # Copyright (c) Twisted Matrix Laboratories. 2 # See LICENSE for details. 3 4 """ 5 Test cases for L{twisted.names.ser_num_arith}. 6 """ 7 8 from twisted.names.ser_num_arith import SNA, DateSNA 9 from twisted.trial import unittest 10 11 class SNATest(unittest.TestCase): 12 13 def setUp(self): 14 self.s1 = SNA(1) 15 self.s1a = SNA(1) 16 self.s2 = SNA(2) 17 self.sMaxVal = SNA(SNA.HLFRNG+SNA.HLFRNG-1) 18 19 def test_equality(self): 20 """ 21 Test SNA equality 22 """ 23 self.assertEqual(self.s1, self.s1a) 24 self.assertNotIdentical(self.s1, self.s1a) 25 self.assertEqual(hash(self.s1), hash(self.s1a)) 26 self.assertNotEqual(hash(self.s1), hash(self.s2)) 27 28 def test_le(self): 29 """ 30 Test SNA less than or equal 31 """ 32 self.assertTrue( self.s1 <= self.s1 ) 33 self.assertTrue( self.s1 <= self.s1a ) 34 self.assertTrue( self.s1 <= self.s2 ) 35 self.assertFalse( self.s2 <= self.s1 ) 36 37 def test_ge(self): 38 """ 39 Test SNA greater than or equal 40 """ 41 self.assertTrue( self.s1 >= self.s1 ) 42 self.assertTrue( self.s1 >= self.s1a ) 43 self.assertFalse( self.s1 >= self.s2 ) 44 self.assertTrue( self.s2 >= self.s1 ) 45 46 47 def test_lt(self): 48 """ 49 Test SNA less than 50 """ 51 self.assertFalse( self.s1 < self.s1 ) 52 self.assertFalse( self.s1 < self.s1a ) 53 self.assertTrue( self.s1 < self.s2 ) 54 self.assertFalse( self.s2 < self.s1 ) 55 56 def test_gt(self): 57 """ 58 Test SNA greater than 59 """ 60 self.assertFalse( self.s1 > self.s1 ) 61 self.assertFalse( self.s1 > self.s1a ) 62 self.assertFalse( self.s1 > self.s2 ) 63 self.assertTrue( self.s2 > self.s1 ) 64 65 def test_add(self): 66 """ 67 Test SNA addition 68 """ 69 self.assertEqual( self.s1 + self.s1, self.s2) 70 self.assertEqual( self.s1 + SNA(SNA.MAXADD), SNA(SNA.MAXADD + 1) ) 71 self.assertEqual( SNA(SNA.MAXADD) + SNA(SNA.MAXADD) + SNA(2), SNA(0) ) 72 73 def test_maxval(self): 74 """ 75 Test SNA maxval 76 """ 77 smaxplus1 = self.sMaxVal + self.s1 78 self.assertTrue( smaxplus1 > self.sMaxVal ) 79 self.assertEqual( smaxplus1, SNA(0) ) 80 81 def test_max(self): 82 """ 83 Test the SNA max function 84 """ 85 self.assertEqual( SNA.max([None, self.s1]), self.s1 ) 86 self.assertEqual( SNA.max([self.s1, None]), self.s1 ) 87 self.assertEqual( SNA.max([self.s1, self.s1a]), self.s1 ) 88 self.assertEqual( SNA.max([self.s2, self.s1a, self.s1, None]), self.s2 ) 89 self.assertEqual( SNA.max([SNA(SNA.MAXADD), self.s2, self.s1a, self.s1, None]), SNA(SNA.MAXADD) ) 90 self.assertEqual( SNA.max([self.s2, self.s1a, self.s1, None, self.sMaxVal]), self.s2 ) 91 92 def test_dateSNA(self): 93 """ 94 Test DateSNA construction and comparison 95 """ 96 date1 = DateSNA('20120101000000') 97 date2 = DateSNA('20130101000000') 98 self.assertTrue( date1 < date2 ) 99 100 def test_dateAdd(self): 101 """ 102 Test DateSNA addition 103 """ 104 date3 = DateSNA('20370101000000') 105 sna1 = SNA(365*24*60*60) 106 date4 = date3 + sna1 107 self.assertEqual( date4.asInt(), date3.asInt() + sna1.asInt()) 108 109 def test_asDate(self): 110 """ 111 Test DateSNA conversion 112 """ 113 date1 = '20120101000000' 114 date1Sna = DateSNA(date1) 115 self.assertEqual(date1Sna.asDate(), date1) 116 117 def test_roundTrip(self): 118 """ 119 Test DateSNA conversion 120 """ 121 date1 = '20370101000000' 122 date1Sna = DateSNA(date1) 123 intval = date1Sna.asInt() 124 sna1a = SNA(intval) 125 126 dateSna1a = DateSNA.fromSNA(sna1a) 127 self.assertEqual(date1Sna, dateSna1a) 128 129 dateSna2 = DateSNA.fromInt(intval) 130 self.assertEqual(date1Sna, dateSna2) 131 132 No newline at end of file
