Ticket #5454: addEdsn0AndDnssec5454V04.patch
| File addEdsn0AndDnssec5454V04.patch, 105.1 KB (added by BobNovas, 14 months ago) |
|---|
-
doc/names/examples/index.xhtml
15 15 <li><a href="testdns.py">testdns.py</a> - Prints the results of an Address record lookup, Mail-Exchanger record lookup, and Nameserver record lookup for the given hostname for a given hostname.</li> 16 16 <li><a href="dns-service.py">dns-service.py</a> - Searches for SRV records in DNS.</li> 17 17 <li><a href="gethostbyname.py">gethostbyname.py</a> - Returns the IP address for a given hostname.</li> 18 <li><a href="dnssecTest.py">dnssecTest.py</a></li> 18 19 </ul> 19 20 </body> 20 21 </html> -
doc/names/examples/testdnssec.py
1 #!/usr/bin/env python 2 3 # Copyright (c) Twisted Matrix Laboratories. 4 # See LICENSE for details. 5 6 """ 7 Sample app to lookup DS records and show a DNSSEC result 8 """ 9 10 import sys 11 from twisted.names.common import DnssecConfig 12 from twisted.names.client import Resolver 13 from twisted.names import client 14 from twisted.internet import reactor 15 16 def deferredAnswer(result): 17 #expect - a 4-tuple with a couple of DS RR's and an RRSIG RR in the answer. 18 print " Answer: %s\n Authority: %s\n Additional: %s\n Message: %s" % result 19 20 #expect - the AD bit to be set 21 message = result[3] 22 authData = not not message.authData 23 print "expect authData to be True: %s" % authData 24 25 reactor.stop() 26 27 def errAnswer(error): 28 print "Error: %s" % error 29 reactor.stop() 30 31 def main(): 32 33 reactor.callWhenRunning(doLookup) 34 reactor.run() 35 36 def doLookup(): 37 38 #DnssecConfig - set ednsEnabled True if dnssecOk is True or you won't get 39 # a DNSSEC result - since DO is in the EDNS OPT record. 40 #For efficiency, set maxUdpPktSz large enough to get a DNSSEC message 41 # without falling back to TCP but not so large that a network with small 42 # MTU fragments packets. 1492 is generally absolutely safe. 43 # 4096 usually works. It depends on the network. 44 dsc = DnssecConfig(ednsEnabled=True, maxUdpPktSz=4096, dnssecOk=True, chkDis=False) 45 46 #setup a DNSSEC resolver using a public validating resolver 47 # and set it as the client's theResolver 48 resolver = Resolver(servers=[('149.20.64.20', 53)], dnssecConfig=dsc) 49 client.theResolver = resolver 50 51 #query for DS records for comcast.net 52 client.lookupDS('comcast.net')\ 53 .addCallback(deferredAnswer)\ 54 .addErrback(errAnswer) 55 56 if __name__ == '__main__': 57 main() 58 No newline at end of file -
doc/names/howto/names.xhtml
49 49 directives are not yet supported. 50 50 </p> 51 51 52 <h2>Using DNS Security Extensions (DNSSEC)</h2> 53 54 <p>DNSSEC adds data origin authentication and data integrity to the Domain Name System (see <a href="http://www.ietf.org/rfc/rfc4033.txt">RFC4033</a>.) To use DNSSEC requires EDNS0, because to enable DNSSEC requires setting the DNSSEC OK (DO) bit which is in the EDNS0 OPT Record. <a href="http://www.ietf.org/rfc/rfc4035.txt"> RFC4035</a> discusses how a non-validating security aware resolver (which is what twisted.names is with the DNSSEC change) should handle the DO, CD and AD bits. 55 </p> 56 57 <p><a href="../../../doc/names/examples/dnssecTest.py" class="py-listings">dnssecTest.py</a> is an example of using DNSSEC to check the AD bit of a domain that should validate. 58 </p> 59 52 60 </body></html> -
twisted/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 … … 99 104 for DNS datagrams, and enforce timeouts. If not provided, the 100 105 global reactor will be used. 101 106 107 @param dnssecConfig: An L{DnssecConfig} - see common.DnssecConfig() 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)385 391 392 # if dnssecOk is enabled, return a reference to the message as the 393 # 4th member of the tuple, so the caller can access the message header 394 # flags. There are more flags than just AD (authentic Data) that are 395 # set in a response that may be of interest (e.g., Truncate-TC). 396 if self.dnssecConfig.dnssecOk: 397 return (message.answers, message.authority, 398 message.additional, message) 399 else: 400 #dnssecOk was not requested - return a legacy 3-tuple 401 return (message.answers, message.authority, message.additional) 386 402 403 387 404 def _lookup(self, name, cls, type, timeout): 388 405 """ 389 406 Build a L{dns.Query} for the given parameters and dispatch it via UDP. … … 953 970 @rtype: C{Deferred} 954 971 """ 955 972 return getResolver().lookupNamingAuthorityPointer(name, timeout) 973 974 975 def lookupDNSKey(name, timeout=None): 976 """ 977 DNSKEY lookup. 978 979 @type name: C{str} 980 @param name: DNS name to resolve. 981 982 @type timeout: Sequence of C{int} 983 @param timeout: Number of seconds after which to reissue the query. 984 When the last timeout expires, the query is considered failed. 985 986 @rtype: C{Deferred} 987 988 @since: 12.1 989 """ 990 return getResolver().lookupDNSKey(name, timeout) 991 992 993 def lookupDS(name, timeout=None): 994 """ 995 DS lookup. 996 997 @type name: C{str} 998 @param name: DNS name to resolve. 999 1000 @type timeout: Sequence of C{int} 1001 @param timeout: Number of seconds after which to reissue the query. 1002 When the last timeout expires, the query is considered failed. 1003 1004 @rtype: C{Deferred} 1005 1006 @since: 12.1 1007 """ 1008 return getResolver().lookupDS(name, timeout) 1009 1010 1011 def lookupNSEC(name, timeout=None): 1012 """ 1013 NSEC lookup. 1014 1015 @type name: C{str} 1016 @param name: DNS name to resolve. 1017 1018 @type timeout: Sequence of C{int} 1019 @param timeout: Number of seconds after which to reissue the query. 1020 When the last timeout expires, the query is considered failed. 1021 1022 @rtype: C{Deferred} 1023 1024 @since: 12.1 1025 """ 1026 return getResolver().lookupNSEC(name, timeout) 1027 1028 1029 def lookupNSEC3(name, timeout=None): 1030 """ 1031 NSEC3 lookup. 1032 1033 @type name: C{str} 1034 @param name: DNS name to resolve. 1035 1036 @type timeout: Sequence of C{int} 1037 @param timeout: Number of seconds after which to reissue the query. 1038 When the last timeout expires, the query is considered failed. 1039 1040 @rtype: C{Deferred} 1041 1042 @since: 12.1 1043 """ 1044 return getResolver().lookupNSEC3(name, timeout) 1045 1046 1047 def lookupNSEC3Param(name, timeout=None): 1048 """ 1049 NSEC3 Param lookup. 1050 1051 @type name: C{str} 1052 @param name: DNS name to resolve. 1053 1054 @type timeout: Sequence of C{int} 1055 @param timeout: Number of seconds after which to reissue the query. 1056 When the last timeout expires, the query is considered failed. 1057 1058 @rtype: C{Deferred} 1059 1060 @since: 12.1 1061 """ 1062 return getResolver().lookupNSEC3Param(name, timeout) 1063 1064 1065 def lookupRRSIG(name, timeout=None): 1066 """ 1067 RRSIG lookup. 1068 1069 @type name: C{str} 1070 @param name: DNS name to resolve. 1071 1072 @type timeout: Sequence of C{int} 1073 @param timeout: Number of seconds after which to reissue the query. 1074 When the last timeout expires, the query is considered failed. 1075 1076 @rtype: C{Deferred} 1077 1078 @since: 12.1 1079 """ 1080 return getResolver().lookupRRSIG(name, timeout) -
twisted/names/common.py
18 18 19 19 EMPTY_RESULT = (), (), () 20 20 21 22 23 class DnssecConfig(): 24 """ 25 Sets recDes and DNSSEC parameters. See the following RFC's for details: 26 27 U{RFC 4033: DNS Security Introduction and Requirements 28 <http://www.ietf.org/rfc/rfc4033.txt>} 29 30 U{RFC 4034: Resource Records for the DNS Security Extensions 31 <http://www.ietf.org/rfc/rfc4034.txt>} 32 33 U{RFC 4035: Protocol Modifications for the DNS Security Extensions 34 <http://www.ietf.org/rfc/rfc4035.txt>} 35 36 @type recDes: C{bool} 37 @ivar recDes: Recursion Desired (RD flag). Not a DNSSEC parameter and does 38 not require L{ednsEnabled}, but still nice to be able to control 39 whether or not you're asking for recursion. 40 41 @type ednsEnabled: C{bool} 42 @ivar ednsEnabled: If True, adds an OPT record to the query. 43 The OPT record contains a version field (see L{version}) that 44 indicates the version of EDNS that you can handle. 45 46 @type maxUdpPktSz: C{int} 47 @ivar maxUdpPktSz: The max size UDP packet (bytes) that your end-to-end 48 network can handle. On a modern network a reliable size is 1492, 49 although up to 65535 is possible. Requires L{ednsEnabled} to be True. 50 51 @type dnssecOK: C{bool} 52 @ivar dnssecOK: Dnssec Ok (DO flag). If True, sets a flag that indicates 53 you want DNSSEC RR's and validation if the resolver validates. If DO 54 is set, AD will be set in the response if the answer validates. 55 Requires L{ednsEnabled}. 56 57 @type chkDis: C{bool} 58 @ivar chkDis: Checking Disabled (CD flag). If dnssecOk and chkDis are both 59 True, a validating resolver won't do validation but will return the 60 DNSSEC RR's so that YOU can. Requires L{ednsEnabled} 61 62 @type version: C{int} 63 @ivar version: Sets the EDNS version level. Currently, only version 0 is 64 defined and supported by U{RFC 2671: Extension Mechanisms for DNS 65 (EDNS0)<http://www.ietf.org/rfc/rfc2671.txt>} 66 67 @since: 12.1 68 """ 69 def __init__(self, 70 recDes=True, 71 ednsEnabled=False, 72 maxUdpPktSz=512, 73 dnssecOk=False, 74 chkDis=False, 75 version=0): 76 77 self.recDes = recDes 78 self.ednsEnabled = ednsEnabled 79 self.maxUdpPktSz = maxUdpPktSz 80 self.dnssecOk = dnssecOk 81 self.chkDis = chkDis 82 self.version = version 83 84 assert not self.ednsEnabled or 512 <= self.maxUdpPktSz <= 65535 85 assert version == 0 86 87 88 21 89 class ResolverBase: 22 90 """ 23 91 L{ResolverBase} is a base class for L{IResolver} implementations which … … 36 104 37 105 typeToMethod = None 38 106 39 def __init__(self ):107 def __init__(self, dnssecConfig=None): 40 108 self.typeToMethod = {} 41 109 for (k, v) in typeToMethod.items(): 42 110 self.typeToMethod[k] = getattr(self, v) 111 self.dnssecConfig = dnssecConfig 112 if self.dnssecConfig == None: 113 self.dnssecConfig = DnssecConfig() 43 114 44 45 115 def exceptionForCode(self, responseCode): 46 116 """ 47 117 Convert a response code (one of the possible values of … … 201 271 """ 202 272 return self._lookup(name, dns.IN, dns.ALL_RECORDS, timeout) 203 273 274 275 def lookupDNSKey(self, name, timeout=None): 276 """ 277 @see: twisted.names.client.lookupDNSKey 278 279 @since: 12.1 280 """ 281 return self._lookup(name, dns.IN, dns.DNSKEY, timeout) 282 283 284 def lookupDS(self, name, timeout=None): 285 """ 286 @see: twisted.names.client.lookupDS 287 288 @since: 12.1 289 """ 290 return self._lookup(name, dns.IN, dns.DS, timeout) 291 292 293 def lookupNSEC(self, name, timeout=None): 294 """ 295 @see: twisted.names.client.lookupNSEC 296 297 @since: 12.1 298 """ 299 return self._lookup(name, dns.IN, dns.NSEC, timeout) 300 301 302 def lookupNSEC3(self, name, timeout=None): 303 """ 304 @see: twisted.names.client.lookupNSEC3 305 306 @since: 12.1 307 """ 308 return self._lookup(name, dns.IN, dns.NSEC3, timeout) 309 310 311 def lookupNSEC3Param(self, name, timeout=None): 312 """ 313 @see: twisted.names.client.lookupNSEC3Param 314 315 @since: 12.1 316 """ 317 return self._lookup(name, dns.IN, dns.NSEC3PARAM, timeout) 318 319 320 def lookupRRSIG(self, name, timeout=None): 321 """ 322 @see: twisted.names.client.lookupRRSIG 323 324 @since: 12.1 325 """ 326 return self._lookup(name, dns.IN, dns.RRSIG, timeout) 327 328 204 329 def getHostByName(self, name, timeout = None, effort = 10): 205 330 """ 206 331 @see: twisted.names.client.getHostByName … … 268 393 dns.MX: 'lookupMailExchange', 269 394 dns.TXT: 'lookupText', 270 395 dns.SPF: 'lookupSenderPolicy', 396 dns.DNSKEY:'lookupDNSKey', 397 dns.DS: 'lookupDS', 398 dns.NSEC: 'lookupNSEC', 399 dns.NSEC3: 'lookupNSEC3', 400 dns.NSEC3PARAM: 'lookupNSEC3Param', 401 dns.RRSIG: 'lookupRRSIG', 271 402 272 403 dns.RP: 'lookupResponsibility', 273 404 dns.AFSDB: 'lookupAFSDatabase', -
twisted/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_NULL', 'Record_PTR', 'Record_RP', 'Record_SOA', 32 'Record_SPF', 'Record_SRV', 'Record_TXT', 'Record_WKS', 'UnknownRecord', 33 'Record_NS', 'Record_NSEC', 'Record_NSEC3', 'Record_NULL', 'Record_OPT', 34 'Record_PTR', 'Record_RP', 'Record_RRSIG', 'Record_SOA', 'Record_SPF', 35 'Record_SRV', 'Record_TXT', 'Record_WKS', 'UnknownRecord', 33 36 34 37 'QUERY_CLASSES', 'QUERY_TYPES', 'REV_CLASSES', 'REV_TYPES', 'EXT_QUERIES', 35 38 36 'Charstr', 'Message', 'Name', ' Query', 'RRHeader', 'SimpleRecord',37 ' DNSDatagramProtocol', 'DNSMixin', 'DNSProtocol',39 'Charstr', 'Message', 'Name', 'OPTHeader', 'Query', 'RRHeader', 40 'SimpleRecord','DNSDatagramProtocol', 'DNSMixin', 'DNSProtocol', 38 41 39 42 'OK', 'OP_INVERSE', 'OP_NOTIFY', 'OP_QUERY', 'OP_STATUS', 'OP_UPDATE', 40 43 'PORT', … … 46 49 # System imports 47 50 import warnings 48 51 52 import re 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 58 63 # Twisted imports 59 64 from twisted.internet import protocol, defer … … 61 66 from twisted.python import log, failure 62 67 from twisted.python import util as tputil 63 68 from twisted.python import randbytes 69 from twisted.names.ser_num_arith import SNA, DateSNA 64 70 65 71 66 72 def randomSource(): … … 79 85 NAPTR = 35 80 86 A6 = 38 81 87 DNAME = 39 88 OPT = 41 89 DS = 43 90 RRSIG = 46 91 NSEC = 47 92 DNSKEY = 48 93 NSEC3 = 50 94 NSEC3PARAM = 51 82 95 SPF = 99 83 96 84 97 QUERY_TYPES = { … … 108 121 NAPTR: 'NAPTR', 109 122 A6: 'A6', 110 123 DNAME: 'DNAME', 111 SPF: 'SPF' 124 OPT: 'OPT', 125 DS: 'DS', 126 RRSIG: 'RRSIG', 127 NSEC: 'NSEC', 128 DNSKEY: 'DNSKEY', 129 NSEC3: 'NSEC3', 130 NSEC3PARAM: 'NSEC3PARAM', 131 SPF: 'SPF', 112 132 } 113 133 114 134 IXFR, AXFR, MAILB, MAILA, ALL_RECORDS = range(251, 256) … … 371 391 def __str__(self): 372 392 return self.name 373 393 394 class Sigstr(object): 395 """ 396 for signatures and keys. display as b64 encoded 397 398 @since: 12.1 399 """ 400 implements(IEncodable) 401 402 def __init__(self, string=''): 403 if not isinstance(string, str): 404 raise ValueError("%r is not a string" % (string, )) 405 self.string = string # b64encoded string 406 407 def encode(self, strio, compDict=None): 408 """ 409 Write the byte representation (the un-b64-encoded string) 410 to the file. 411 412 @type strio: file 413 @param srio: The byte representation of this signature or key 414 will be written to this file 415 416 @type compDict: dict 417 @param compDict: not used. 418 """ 419 strio.write(b64decode(self.string)) 420 421 def decode(self, strio, length=None): 422 """ 423 Decode a signature or a key. 424 425 @type strio: file 426 @param strio: Exactly length bytes will be read from this file 427 to decode the full signature or key 428 429 @type length: int 430 @param lenth: length must always be given. A signature or key 431 is always the last thing in an RR and so you can always determine 432 its length. 433 """ 434 self.string = '' 435 if length == None: 436 return 437 438 assert isinstance(length, int) 439 buff = readPrecisely(strio, length) 440 self.string = b64encode(buff) 441 442 def __eq__(self, other): 443 if isinstance(other, Sigstr): 444 return self.string == other.string 445 return False 446 447 def __hash__(self): 448 return hash(self.string) 449 450 def __str__(self): 451 return self.string 452 453 454 class TypeBitmaps(object): 455 """ 456 bitmap encoding scheme used by NSEC and NSEC3 RR's 457 to indicate the RRset types that exist at the 458 NSEC/NSEC3 RR's original owner name or hashed name. 459 460 See the following RFC's for details: 461 462 U{RFC 4034: Resource Records for the DNS Security Extensions 463 <http://www.ietf.org/rfc/rfc4034.txt>} 464 465 U{RFC 5155: DNS Security (DNSSEC) Hashed Authenticated Denial of 466 Existence <http://tools.ietf.org/rfc/rfc5155.txt>} 467 468 @since: 12.1 469 """ 470 fmt = 'BB' 471 typeRegex = re.compile('TYPE(\d+)') 472 473 def __init__(self, string=''): 474 self.string = string 475 476 def encode(self, strio, compDict=None): 477 """ 478 Encode the string field, which consists of a set 479 of type names, into an NSEC/NSEC3 type bitmap. 480 481 @type strio: file 482 @param strio: the byte representation of the type bitmap 483 will be written to this file. 484 485 @type compDict: dict 486 @param compDict: not used. 487 """ 488 if not self.string: 489 return; 490 491 # get a sorted list of RR Type Values 492 mnus = self.string.split(' ') 493 mnuVals = [] 494 for mnu in mnus: 495 mnuVal = REV_TYPES.get(mnu, None) 496 if not mnuVal: 497 m = self.typeRegex.match(mnu) 498 if m.groups(): 499 mnuVal = int(m.group(1)) 500 assert mnuVal < 65536 501 else: 502 log.err("can't parse %s in %s" % (mnu, self.string, )) 503 continue; 504 mnuVals.append(mnuVal) 505 mnuVals.sort() 506 507 # convert that to a dict of windows and lists 508 windDict = {} 509 for v in mnuVals: 510 window = (v >> 8) & 0xFF 511 if window not in windDict: 512 windDict[window] = [] 513 windDict[window].append(v & 0xFF) 514 515 # have to sort the keys - they're not in order! 516 windows = windDict.keys() 517 windows.sort() 518 519 # create the bitmaps 520 bmap = bytearray() 521 for w in windows: 522 bmapseg = bytearray(32) 523 maxoff = 0 524 for v in windDict[w]: 525 vm1 = v - 1 526 off = vm1 >> 3 527 bit = vm1 & 0x7 528 msk = 1 << bit 529 bmapseg[off] |= msk 530 maxoff = max(off, maxoff) 531 bmapseg = bmapseg[0:maxoff+1] 532 bmap += chr(w) + chr(maxoff+1) + bmapseg 533 534 strio.write(str(bmap)) 535 536 def decode(self, strio, length=None): 537 """ 538 Decode an NSEC/NSEC3 type bitmap into a string 539 representation of type names. 540 """ 541 self.type_bitmaps = "" 542 if length == None: 543 return 544 545 type_bitmaps = bytearray() 546 l = struct.calcsize(self.fmt) 547 parsed_length = 0 548 while parsed_length < length: 549 buff = readPrecisely(strio, l) 550 wb_num, bm_len = struct.unpack(self.fmt, buff) 551 assert parsed_length + 2 + bm_len <= length 552 bm = readPrecisely(strio, bm_len) 553 byteNum = -1 554 for b in bm: 555 byteNum += 1 556 ob = ord(b) 557 if ob == 0: 558 continue 559 560 for v in range(8): 561 msk = 1<<v 562 if ob & msk: 563 val = wb_num*256 + byteNum*8 + v + 1 564 mnu = QUERY_TYPES.get(val, None) 565 if not mnu: 566 mnu = 'TYPE' + str(val) 567 type_bitmaps += (mnu + ' ') 568 569 parsed_length += 2 + bm_len 570 571 self.type_bitmaps = str(type_bitmaps[0:-1]) 572 573 def __eq__(self, other): 574 if isinstance(other, TypeBitmaps): 575 return self.string == other.string 576 return False 577 578 def __hash__(self): 579 return hash(self.string) 580 581 def __str__(self): 582 return self.string 583 374 584 class Query: 375 585 """ 376 586 Represent a single DNS query. … … 434 644 return 'Query(%r, %r, %r)' % (str(self.name), self.type, self.cls) 435 645 436 646 437 class RRHeader(tputil.FancyEqMixin): 647 648 class OPTHeader(tputil.FancyEqMixin): 438 649 """ 650 A OPT record header. 651 652 @cvar fmt: C{str} specifying the byte format of an OPT Header. 653 654 @ivar name: Root (0, 8-bits) 655 @ivar type: 41 (OPT Record) 656 @ivar payload: An object that implements the IEncodable interface 657 @ivar auth: Whether this header is authoritative or not. 658 659 @since: 12.1 660 """ 661 662 implements(IEncodable) 663 664 compareAttributes = ('name', 'type', 'payload', 'auth') 665 666 fmt = "!H" 667 668 name = None 669 type = None 670 payload = None 671 672 # OPTHeader _really_ has no ttl or rdlength, but the 673 # existence of the attributes is required. 674 ttl = None 675 rdlength = None 676 677 cachedResponse = None 678 679 680 def __init__(self, payload=None, auth=False): 681 """ 682 @type name: C{str} 683 @param name: Root (0) 684 685 @type type: C{int} 686 @param type: Query type 41. 687 688 @type payload: An object implementing C{IEncodable} 689 @param payload: The OPT payload 690 """ 691 assert (payload is None) or (payload.TYPE == OPT) 692 693 self.name = 0 694 self.type = OPT 695 self.payload = payload 696 self.auth = auth 697 698 699 def encode(self, strio, compDict=None): 700 """ 701 Encode this OPT record header into proper format 702 703 @type strio: file 704 @param strio: the byte representation of this OPTHeader will be written 705 to this file. 706 707 @type compDict: dict 708 @param compDict: not used. 709 """ 710 strio.write(struct.pack('!B', 0)) 711 strio.write(struct.pack(self.fmt, self.type)) 712 if self.payload: 713 prefix = strio.tell() 714 self.payload.encode(strio, compDict) 715 aft = strio.tell() 716 strio.seek(prefix - 2, 0) 717 strio.write(struct.pack('!H', aft - prefix)) 718 strio.seek(aft, 0) 719 720 721 def decode(self, strio, length = None): 722 """ 723 Decode a byte string into this OPTHeader. 724 725 @type strio: file 726 @param strio: Bytes will be read from this file until the full 727 OPTHeader is decoded. 728 """ 729 self.name.decode(strio) 730 l = struct.calcsize(self.fmt) 731 buff = readPrecisely(strio, l) 732 r = struct.unpack(self.fmt, buff) 733 self.type = r[0] 734 735 736 def isAuthoritative(self): 737 return self.auth 738 739 740 def __str__(self): 741 return '<OPT auth=%s>' % (self.auth and 'True' or 'False') 742 743 744 @classmethod 745 def _headerFactory(cls, strio, auth=False): 746 """ 747 reads enough of the stream to figure out if what is there is 748 an OPTHeader or an RRHeader 749 """ 750 beginPos = strio.tell() 751 name = Name() 752 name.decode(strio) 753 type = struct.unpack(cls.fmt, readPrecisely(strio, 2))[0] 754 755 if len(name.name) == 0 and type == OPT: 756 return cls() 757 else: 758 # back up to the beginning and try again 759 strio.seek(beginPos, 0) 760 rrh = RRHeader(auth=auth) 761 rrh.decode(strio) 762 return rrh 763 764 __repr__ = __str__ 765 766 767 768 class RRHeader(OPTHeader): 769 """ 439 770 A resource record header. 440 771 441 772 @cvar fmt: C{str} specifying the byte format of an RR. … … 445 776 @ivar cls: The query class of the original request. 446 777 @ivar ttl: The time-to-live for this record. 447 778 @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. 779 @ivar auth: Whether this header is authoritative or not. 451 780 """ 452 781 453 782 implements(IEncodable) … … 1050 1379 1051 1380 fancybasename = 'SRV' 1052 1381 compareAttributes = ('priority', 'weight', 'target', 'port', 'ttl') 1053 showAttributes = ('priority', 'weight', ('target', 'target', '%s'), 'port', 'ttl') 1382 showAttributes = ('priority', 'weight', 1383 ('target', 'target', '%s'), 'port', 'ttl') 1054 1384 1055 1385 def __init__(self, priority=0, weight=0, port=0, target='', ttl=None): 1056 1386 self.priority = int(priority) … … 1464 1794 1465 1795 1466 1796 1797 class Record_OPT(tputil.FancyEqMixin, tputil.FancyStrMixin): 1798 """ 1799 EDNS0 Option record. 1800 1801 @type payload_size: C{int} 1802 @ivar payload_size: Specifies the max UDP Packet size (bytes) that your 1803 network can handle. 1804 1805 @type dnssecOk: C{bool} 1806 @ivar dnssecOk: Requests the server to send DNSSEC RRs and to do DNSSEC 1807 validation (and set the AD bit if the response validates). 1808 1809 @type version: C{int} 1810 @ivar version: The version of DNSSEC used. Currently only version 0 1811 is defined. 1812 1813 @since: 12.1 1814 """ 1815 implements(IEncodable, IRecord) 1816 TYPE = OPT 1817 fmt = '!HBBHH' 1818 1819 fancybasename = 'OPT' 1820 showAttributes = ('payload_size', ('flags', 'flags', '0x%x'), 'version') 1821 compareAttributes = ('payload_size', 'flags', 'version') 1822 1823 1824 def __init__(self, payload_size=512, dnssecOk=0, version=0, ttl=None): 1825 self.payload_size = payload_size 1826 self.version = version 1827 self.flags = (dnssecOk & 1) << 15 1828 1829 1830 def encode(self, strio, compDict = None): 1831 OPTHeader().encode(strio) 1832 strio.write(struct.pack('!H', self.payload_size)) 1833 strio.write(struct.pack('!B', 0)) # high order 0 1834 strio.write(struct.pack('!B', self.version)) 1835 strio.write(struct.pack('!H', self.flags)) # DO(bit) + Z's 1836 strio.write(struct.pack('!H', 0)) # Data length: 0 1837 1838 1839 def decode(self, strio, length=None): 1840 """ 1841 are OPT Records always 0 rdlength? 1842 """ 1843 l = struct.calcsize(self.fmt) 1844 buff = readPrecisely(strio, l) 1845 r = struct.unpack(self.fmt, buff) 1846 self.payload_size, z, self.version, self.flags, length = r 1847 assert length == 0 1848 1849 1850 def __hash__(self): 1851 return hash((self.payload_size, self.version, self.flags)) 1852 1853 1854 1855 class Record_RRSIG(tputil.FancyEqMixin, tputil.FancyStrMixin): 1856 """ 1857 DNSSEC RRSIG record. See RFC 4034 for details. 1858 1859 @type type_covered: C{int} 1860 @ivar type_covered: Identifies the type of the RRset that this RRSIG covers. 1861 1862 @type algo: C{int} 1863 @ivar algo: Identifies the crypto algorithm type used to create the 1864 signature. 1865 (5 - RSH/SHA-1 is mandatory. See RFC 4034 App A.1 for the full list.) 1866 1867 @type labels: C{int} 1868 @ivar labels: Specifies the number of labels in the original RRSIG RR 1869 owner name. A validator can use this to determine whether the answer 1870 was synthesized from a wildcard. 1871 1872 @type original_ttl: C{int} 1873 @ivar original_ttl: Specifies the TTL of the covered RRset as it appears 1874 in the authoritative zone. 1875 1876 @type sig_expiration: C{int} 1877 @ivar sig_expiration: This RRSIG must NOT be used after this time. Seconds 1878 since 1/1/1970, Modulo 2**32, compare using DNS Serial Number Arithmetic 1879 1880 @type sig_inception: C{int} 1881 @ivar sig_inception: This RRSIG must NOT be used prior to this time. Seconds 1882 since 1/1/1970, Modulo 2**32, compare using DNS Serial Number Arithmetic 1883 1884 @type key_tag: C{int} 1885 @ivar key_tag: Contains the key tag value of the DNSKEY RR that validates 1886 this signature, in network byte order. See RFC 4034 App B. 1887 1888 @type signers_name: L{Name} 1889 @ivar signers_name: Identifies the owner name of the DNSKEY RR that a 1890 validator should use to validate this signature. Must not use DNS 1891 name compression. 1892 1893 @type signature: L{Sigstr} 1894 @ivar signature: Contains the cryptographic signature that covers the RRSIG 1895 RDATA (excluding the Signature field and the RRset specified by the 1896 RRSIG owner name, RRSIG class and RRSIG Type Covered fields. 1897 1898 @type ttl: C{int} 1899 @ivar ttl: The maximum number of seconds which this record should be 1900 cached. 1901 1902 @since: 12.1 1903 """ 1904 implements(IEncodable, IRecord) 1905 TYPE = RRSIG 1906 fmt = '!HBBIIIH' 1907 1908 fancybasename = 'RRSIG' 1909 showAttributes = ('type_covered', 'algo', 'labels', 'original_ttl', 1910 ('_sig_expiration', 'sig_expiration', '%s'), 1911 ('_sig_inception', 'sig_inception', '%s'), 1912 'key_tag', 1913 ('signers_name', 'signers_name', '%s'), 1914 ('_signature', 'signature', '%s'), 'ttl') 1915 compareAttributes = ('type_covered', 'algo', 'labels', 'original_ttl', 1916 'sig_expiration', 'sig_inception', 'key_tag', 1917 'signers_name', 'signature', 'ttl') 1918 1919 _sig_expiration = property(lambda self: str(self.sig_expiration)) 1920 _sig_inception = property(lambda self: str(self.sig_inception)) 1921 _signature = property(lambda self: self.signature.string) 1922 1923 1924 def __init__(self, type_covered=A, algo=0, labels=0, original_ttl=0, 1925 sig_expiration='', sig_inception='', key_tag=0, 1926 signers_name='', signature='', ttl=None): 1927 self.type_covered = type_covered 1928 self.algo = algo 1929 self.labels = labels 1930 self.original_ttl = original_ttl 1931 self.sig_expiration = DateSNA(sig_expiration) 1932 self.sig_inception = DateSNA(sig_inception) 1933 self.key_tag = key_tag 1934 self.signers_name = Name(signers_name) 1935 self.signature = Sigstr(signature) 1936 self.ttl = str2time(ttl) 1937 1938 1939 def encode(self, strio, compDict = None): 1940 strio.write(struct.pack(self.fmt, 1941 self.type_covered, 1942 self.algo, 1943 self.labels, 1944 self.original_ttl, 1945 self.sig_expiration.asInt(), 1946 self.sig_inception.asInt(), 1947 self.key_tag)) 1948 self.signers_name.encode(strio, None) 1949 self.signature.encode(strio, compDict) 1950 1951 1952 def decode(self, strio, length=None): 1953 start = strio.tell() 1954 l = struct.calcsize(self.fmt) 1955 buff = readPrecisely(strio, l) 1956 r = struct.unpack(self.fmt, buff) 1957 self.type_covered, self.algo, self.labels, self.original_ttl, \ 1958 sig_expiration, sig_inception, self.key_tag = r 1959 self.sig_expiration = DateSNA.fromInt(sig_expiration) 1960 self.sig_inception = DateSNA.fromInt(sig_inception) 1961 self.signers_name.decode(strio) 1962 here = strio.tell() 1963 self.signature.decode(strio, length + start - here if length else None) 1964 1965 1966 def __hash__(self): 1967 return hash((self.type_covered, self.algo, self.labels, self.original_ttl, 1968 self.sig_expiration, self.sig_inception, self.key_tag, 1969 self.signers_name, self.signature)) 1970 1971 1972 1973 class Record_DS(tputil.FancyEqMixin, tputil.FancyStrMixin): 1974 """ 1975 A DNSSEC DS record. 1976 1977 @type key_tag: C{int} 1978 @ivar key_tag: Lists the key tag of the DNSKEY RR referred to by this DS 1979 record. 1980 1981 @type algo: C{int} 1982 @ivar algo: Lists the algorithm number of the DNSKEY RR referenced by this 1983 DS record. 1984 1985 @type digest_type: C{int} 1986 @ivar digest_type: Identifies the algorithm used to construct the digest 1987 field. 1988 1989 @type digest: L{Sigstr} 1990 @ivar digest: Contains a digest of the refeerenced DNSKEY RR calculated by 1991 the algorithm identified by the digest_type field. 1992 1993 @type ttl: C{int} 1994 @ivar ttl: The maximum number of seconds which this record should be 1995 cached. 1996 1997 @since: 12.1 1998 """ 1999 implements(IEncodable, IRecord) 2000 TYPE = DS 2001 fmt = '!HBB' 2002 2003 fancybasename = 'DS' 2004 showAttributes = ('key_tag', 'algo', 'digest_type', 2005 ('_digest', 'digest', '%s'), 'ttl') 2006 compareAttributes = ('key_tag', 'algo', 'digest_type', 'digest', 'ttl') 2007 2008 _digest = property(lambda self: self.digest.string) 2009 2010 2011 def __init__(self, key_tag=0, algo=0, digest_type=0, digest='', ttl=None): 2012 self.key_tag = key_tag 2013 self.algo = algo 2014 self.digest_type = digest_type 2015 self.digest = Sigstr(digest) 2016 self.ttl = str2time(ttl) 2017 2018 2019 def encode(self, strio, compDict = None): 2020 strio.write(struct.pack(self.fmt, 2021 self.key_tag, 2022 self.algo, 2023 self.digest_type)) 2024 self.digest.encode(strio, None) 2025 2026 2027 def decode(self, strio, length=None): 2028 start = strio.tell() 2029 l = struct.calcsize(self.fmt) 2030 buff = readPrecisely(strio, l) 2031 r = struct.unpack(self.fmt, buff) 2032 self.key_tag, self.algo, self.digest_type = r 2033 here = strio.tell() 2034 self.digest.decode(strio, length + start - here if length else None) 2035 2036 2037 def __hash__(self): 2038 return hash((self.key_tag, self.algo, self.digest_type, self.digest)) 2039 2040 2041 2042 class Record_DNSKEY(tputil.FancyEqMixin, tputil.FancyStrMixin): 2043 """ 2044 A DNSSEC DNSKEY record. Holds the public key for a signed RRset. 2045 2046 @type flags: C{int} 2047 @ivar flags: Bit 7 is the Zone Key flag. If bit 7 has value 1, then the 2048 DNSKEY record holds a DNS zone key and the DNSKEY RR's owner name is 2049 the name of a zone. If bit 7 has value 0, then the DNSKEY record 2050 holds some other type of DNS public key and MUST NOT be used to 2051 verify RRSIGs that cover RRsets. 2052 Bit 15 is the Secure Entry Point flag. See RFC 3757.) 2053 All other bits are reserved and must be zero. 2054 2055 @type protocol: C{int} 2056 @ivar protocol: Must have value 3. The DNSKEY RR must be treated as invalid 2057 if this field does not contain 3. 2058 2059 @type algo: C{int} 2060 @ivar algo: Identifies the public key's cryptographic algorithm and 2061 determines the format of the pub_key field. See RFC 4034 App A. 2062 2063 @type pub_key: L{Sigstr} 2064 @ivar pub_key: Holds the public key material. 2065 2066 @type ttl: C{int} 2067 @ivar ttl: The maximum number of seconds which this record should be 2068 cached. 2069 2070 @since: 12.1 2071 """ 2072 implements(IEncodable, IRecord) 2073 TYPE = DNSKEY 2074 fmt = '!HBB' 2075 2076 fancybasename = 'DNSKEY' 2077 showAttributes = ('flags', 'protocol', 'algo', 2078 ('_pub_key', 'pub_key', '%s'), 'ttl') 2079 compareAttributes = ('flags', 'protocol', 'algo', 'pub_key', 'ttl') 2080 2081 _pub_key = property(lambda self: self.pub_key.string) 2082 2083 2084 def __init__(self, flags=0, protocol=0, algo=0, pub_key='', ttl=None): 2085 self.flags = flags 2086 self.protocol = protocol 2087 self.algo = algo 2088 self.pub_key = Sigstr(pub_key) 2089 self.ttl = str2time(ttl) 2090 2091 2092 def encode(self, strio, compDict = None): 2093 strio.write(struct.pack(self.fmt, 2094 self.flags, 2095 self.protocol, 2096 self.algo)) 2097 self.pub_key.encode(strio, None) 2098 2099 2100 def decode(self, strio, length=None): 2101 start = strio.tell() 2102 l = struct.calcsize(self.fmt) 2103 buff = readPrecisely(strio, l) 2104 r = struct.unpack(self.fmt, buff) 2105 self.flags, self.protocol, self.algo = r 2106 here = strio.tell() 2107 self.pub_key.decode(strio, length + start - here if length else None) 2108 2109 2110 def __hash__(self): 2111 return hash((self.flags, self.protocol, self.algo, self.pub_key)) 2112 2113 2114 2115 class Record_NSEC(tputil.FancyEqMixin, tputil.FancyStrMixin): 2116 """ 2117 A DNSSEC NSEC record provides authenticated denial of existance for DNS 2118 data. 2119 2120 A DNSSEC NSEC record lists: 2121 2122 1) the next owner name in canonical ordering of the zone that contains 2123 authoritative data or a delegation point NS RRset. 2124 2125 2) the set of RR types present at the NSEC RR's owner name. 2126 2127 @type nxt_name: L{Name} 2128 @ivar nxt_name: The next owner name that has authoritative data or contains 2129 a delegation point NS RRset. 2130 2131 @type type_bitmaps: L{TypeBitmaps} 2132 @ivar type_bitmaps: Identifies the RRset types that exist at the NSEC RR's 2133 owner name. 2134 2135 @type ttl: C{int} 2136 @ivar ttl: The maximum number of seconds which this record should be 2137 cached. 2138 2139 @since: 12.1 2140 """ 2141 implements(IEncodable, IRecord) 2142 TYPE = NSEC 2143 2144 fancybasename = 'NSEC' 2145 showAttributes = (('nxt_name', 'nxt_name', '%s'), 2146 ('_type_bitmaps', 'type_bitmaps', '%s'), 'ttl') 2147 compareAttributes = ('nxt_name', 'type_bitmaps', 'ttl') 2148 2149 _type_bitmaps = property(lambda self: self.type_bitmaps.string) 2150 2151 2152 def __init__(self, nxt_name='', type_bitmaps=None, ttl=None): 2153 self.nxt_name = Name(nxt_name) 2154 self.type_bitmaps = TypeBitmaps(type_bitmaps) 2155 self.ttl = str2time(ttl) 2156 2157 2158 def encode(self, strio, compDict = None): 2159 self.nxt_name.encode(strio, None) 2160 self.type_bitmaps.encode(strio, None) 2161 2162 2163 def decode(self, strio, length=None): 2164 start = strio.tell() 2165 self.nxt_name.decode(strio, None) 2166 here = strio.tell() 2167 self.type_bitmaps.decode(strio, length + start - here if length 2168 else None) 2169 2170 2171 def __hash__(self): 2172 return hash((self.nxt_name, self.type_bitmaps)) 2173 2174 2175 2176 class Record_NSEC3PARAM(tputil.FancyEqMixin, tputil.FancyStrMixin): 2177 """ 2178 A DNSSEC NSEC3PARAM record contains the NSEC3 parameters (hash algorithm, 2179 flags, iterations and salt) needed by authoritative servers to calculate 2180 hashed owner names. The presence of an NSEC3PARAM RR at a zone apex 2181 indicates that the specified parameters may be used by authoritative 2182 servers to choose an appropriate set of NSEC3 RRs for negative responses. 2183 2184 @type hash_algo: C{int} 2185 @ivar hash_algo: Identifies the cryptographic hash algorithm used to 2186 construct the hash value. 2187 2188 @type flags: C{int} 2189 @ivar flags: Identifies 8 1-bit flags. The only flag presently defined is 2190 the opt-out flag. If the opt-out flag is set, the NSEC3 record covers 2191 zero or more unsigned delegations. If the opt-out flag is clear, the 2192 NSEC3 record covers zero unsigned delegations. 2193 2194 @type iterations: C{int} 2195 @ivar iterations: Defines the nubmer of additional times the hash algorithm 2196 has been performed. 2197 2198 @type salt: L{Charset} 2199 @ivar salt: Identifies the salt value provided to the hash. 2200 2201 @type ttl: C{int} 2202 @ivar ttl: The maximum number of seconds which this record should be 2203 cached. 2204 2205 @since: 12.1 2206 """ 2207 implements(IEncodable, IRecord) 2208 TYPE = NSEC3 2209 fmt = '!BBH' 2210 2211 fancybasename = 'NSEC3' 2212 showAttributes = ('hash_algo', 'flags', 'iterations', 2213 ('_salt', 'salt', '%s'), 'ttl') 2214 compareAttributes = ('hash_algo', 'flags', 'iterations', 'salt', 'ttl') 2215 2216 _salt = property(lambda self: self.salt.string) 2217 2218 2219 def __init__(self, hash_algo=0, flags=0, iterations=0, salt='', ttl=None): 2220 self.hash_algo = hash_algo 2221 self.flags = flags 2222 self.iterations = iterations 2223 self.salt = Charstr(salt) 2224 self.ttl = str2time(ttl) 2225 2226 2227 def encode(self, strio, compDict = None): 2228 strio.write(struct.pack(self.fmt, 2229 self.hash_algo, 2230 self.flags, 2231 self.iterations)) 2232 self.salt.encode(strio, None) 2233 2234 2235 def decode(self, strio, length=None): 2236 start = strio.tell() 2237 l = struct.calcsize(self.fmt) 2238 buff = readPrecisely(strio, l) 2239 r = struct.unpack(self.fmt, buff) 2240 self.hash_algo, self.flags, self.iterations = r 2241 self.salt.decode(strio) 2242 here = strio.tell() 2243 2244 2245 def __hash__(self): 2246 return hash((self.hash_algo, self.flags, self.iterations, self.salt)) 2247 2248 2249 2250 class Record_NSEC3(Record_NSEC3PARAM): 2251 """ 2252 A DNSSEC NSEC3 record provides non-zone-enumerable authenticated denial of 2253 existence for DNS data and permits a gradual expansion of delegation-centric 2254 zones. 2255 2256 A DNSSEC NSEC3 record lists: 2257 2258 1) the set of RR types present at the original owner name of the NSEC 2259 RR. 2260 2261 2) the next hashed owner name in the hash order of the zone. 2262 2263 @type hash_algo: C{int} 2264 @ivar hash_algo: Identifies the cryptographic hash algorithm used to 2265 construct the hash value. 2266 2267 @type flags: C{int} 2268 @ivar flags: Identifies 8 1-bit flags. The only flag presently defined 2269 is the opt-out flag. If the opt-out flag is set, the NSEC3 record 2270 covers zero or more unsigned delegations. If the opt-out flag is 2271 clear, the NSEC3 record covers zero unsigned delegations. 2272 2273 @type iterations: C{int} 2274 @ivar iterations: Defines the nubmer of additional times the hash algorithm 2275 has been performed. 2276 2277 @type salt: L{Charset} 2278 @ivar salt: Identifies the salt value provided to the hash. 2279 2280 @type nxt_hash_owner_name: L{Charset} 2281 @ivar nxt_hash_owner_name: Contains the next hashed owner name in the zone 2282 in hash order. 2283 2284 @type type_bitmaps: L{TypeBitmaps} 2285 @ivar type_bitmaps: Identifies the RRset types that exist at the NSEC3 RR's 2286 original owner name. 2287 2288 @type ttl: C{int} 2289 @ivar ttl: The maximum number of seconds which this record should be 2290 cached. 2291 2292 @since: 12.1 2293 """ 2294 implements(IEncodable, IRecord) 2295 TYPE = NSEC3 2296 fmt = '!BBH' 2297 2298 fancybasename = 'NSEC3' 2299 showAttributes = ('hash_algo', 'flags', 'iterations', 2300 ('_salt', 'salt', '%s'), 2301 ('nxt_hash_owner_name', 'nxt_hash_owner_name', '%s'), 2302 ('_type_bitmaps', 'type_bitmaps', '%s'), 'ttl') 2303 compareAttributes = ('hash_algo', 'flags', 'iterations', 2304 'salt', 'nxt_hash_owner_name', 'type_bitmaps', 'ttl') 2305 2306 _salt = property(lambda self: self.salt.string) 2307 _type_bitmaps = property(lambda self: self.type_bitmaps.string) 2308 2309 2310 def __init__(self, hash_algo=0, flags=0, iterations=0, salt='', 2311 nxt_hash_owner='', type_bitmaps=None, ttl=None): 2312 Record_NSEC3PARAM.__init__(self, hash_algo, flags, 2313 iterations, salt, ttl) 2314 self.nxt_hash_owner_name = Charstr(nxt_hash_owner) 2315 self.type_bitmaps = TypeBitmaps(type_bitmaps) 2316 2317 2318 def encode(self, strio, compDict = None): 2319 Record_NSEC3PARAM.encode(self, strio, compDict) 2320 self.nxt_hash_owner_name.encode(strio, None) 2321 self.type_bitmaps.encode(strio, None) 2322 2323 2324 def decode(self, strio, length=None): 2325 start = strio.tell() 2326 Record_NSEC3PARAM.decode(self, strio, compDict) 2327 self.nxt_hash_owner_name.decode(strio) 2328 here = strio.tell() 2329 self.type_bitmaps.decode(strio, length + start - here if length 2330 else None) 2331 2332 2333 def __hash__(self): 2334 return hash((self.hash_algo, self.flags, self.iterations, self.salt, 2335 self.nxt_hash_owner_name, self.type_bitmaps)) 2336 2337 2338 1467 2339 # This is a fallback record 1468 2340 class UnknownRecord(tputil.FancyEqMixin, tputil.FancyStrMixin, object): 1469 2341 """ … … 1484 2356 compareAttributes = ('data', 'ttl') 1485 2357 showAttributes = ('data', 'ttl') 1486 2358 2359 1487 2360 def __init__(self, data='', ttl=None): 1488 2361 self.data = data 1489 2362 self.ttl = str2time(ttl) … … 1540 2413 queries = answers = add = ns = None 1541 2414 1542 2415 def __init__(self, id=0, answer=0, opCode=0, recDes=0, recAv=0, 1543 auth=0, rCode=OK, trunc=0, maxSize=512):2416 auth=0, rCode=OK, trunc=0, maxSize=512, authData=0, chkDis=0): 1544 2417 self.maxSize = maxSize 1545 2418 self.id = id 1546 2419 self.answer = answer 1547 2420 self.opCode = opCode 1548 self.auth = auth 1549 self.trunc = trunc 1550 self.recDes = recDes 1551 self.recAv = recAv 2421 self.auth = auth # AA - Authoritative Answer 2422 self.trunc = trunc # TC - TrunCated 2423 self.recDes = recDes # RD - Recursion Desired 2424 self.recAv = recAv # RA - Recursion Available 2425 self.authData = authData # AD - Authentic Data 2426 self.chkDis = chkDis # CD - Checking Disabled 1552 2427 self.rCode = rCode 1553 2428 self.queries = [] 1554 2429 self.answers = [] … … 1588 2463 if self.maxSize and size > self.maxSize: 1589 2464 self.trunc = 1 1590 2465 body = body[:self.maxSize - self.headerSize] 1591 byte3 = (( ( self.answer & 1 ) << 7 ) 1592 | ((self.opCode & 0xf ) << 3 ) 1593 | ((self.auth & 1 ) << 2 ) 1594 | ((self.trunc & 1 ) << 1 ) 1595 | ( self.recDes & 1 ) ) 1596 byte4 = ( ( (self.recAv & 1 ) << 7 ) 1597 | (self.rCode & 0xf ) ) 2466 byte3 = (((self.answer & 1) << 7) 2467 | ((self.opCode & 0xf) << 3) 2468 | ((self.auth & 1 ) << 2) 2469 | ((self.trunc & 1 ) << 1) 2470 | (self.recDes & 1)) 2471 byte4 = (((self.recAv & 1) << 7) 2472 | ((self.authData & 1) << 5) 2473 | ((self.chkDis & 1) << 4) 2474 | (self.rCode & 0xf)) 1598 2475 1599 2476 strio.write(struct.pack(self.headerFmt, self.id, byte3, byte4, 1600 2477 len(self.queries), len(self.answers), … … 1607 2484 header = readPrecisely(strio, self.headerSize) 1608 2485 r = struct.unpack(self.headerFmt, header) 1609 2486 self.id, byte3, byte4, nqueries, nans, nns, nadd = r 1610 self.answer = ( byte3 >> 7) & 11611 self.opCode = ( byte3 >> 3) & 0xf1612 self.auth = ( byte3 >> 2) & 11613 self.trunc = ( byte3 >> 1) & 12487 self.answer = (byte3 >> 7) & 1 2488 self.opCode = (byte3 >> 3) & 0xf 2489 self.auth = (byte3 >> 2) & 1 2490 self.trunc = (byte3 >> 1) & 1 1614 2491 self.recDes = byte3 & 1 1615 self.recAv = ( byte4 >> 7 ) & 1 2492 self.recAv = (byte4 >> 7) & 1 2493 self.authData = (byte4 >> 5) & 1 2494 self.chkDis = (byte4 >> 4) & 1 1616 2495 self.rCode = byte4 & 0xf 1617 2496 1618 2497 self.queries = [] … … 1624 2503 return 1625 2504 self.queries.append(q) 1626 2505 1627 items = ((self.answers, nans), (self.authority, nns), (self.additional, nadd)) 2506 items = ((self.answers, nans), 2507 (self.authority, nns), 2508 (self.additional, nadd)) 1628 2509 for (l, n) in items: 1629 2510 self.parseRecords(l, n, strio) 1630 2511 1631 2512 1632 2513 def parseRecords(self, list, num, strio): 1633 2514 for i in range(num): 1634 header = RRHeader(auth=self.auth)1635 2515 try: 1636 header .decode(strio)2516 header = OPTHeader._headerFactory(strio, auth=self.auth) 1637 2517 except EOFError: 1638 2518 return 1639 2519 t = self.lookupRecordType(header.type) … … 1743 2623 query, or errbacked with any errors that could happen (exceptions 1744 2624 during writing of the query, timeout errors, ...). 1745 2625 """ 1746 m = Message(id, recDes=1) 2626 dnssecConfig = self.controller.dnssecConfig 2627 chkDis = dnssecConfig.chkDis 2628 m = Message(id, recDes=dnssecConfig.recDes, chkDis=chkDis) 1747 2629 m.queries = queries 2630 if dnssecConfig.ednsEnabled: 2631 m.additional = [Record_OPT(payload_size = dnssecConfig.maxUdpPktSz, 2632 version = dnssecConfig.version, 2633 dnssecOk = dnssecConfig.dnssecOk)] 1748 2634 1749 2635 try: 1750 2636 writeMessage(m) … … 1798 2684 self.transport.write(message.toStr(), address) 1799 2685 1800 2686 def startListening(self): 1801 self._reactor.listenUDP(0, self, maxPacketSize=512) 2687 maxPacketSize = 512 2688 if self.controller.dnssecConfig.ednsEnabled: 2689 maxPacketSize = self.controller.dnssecConfig.maxUdpPktSz 2690 self._reactor.listenUDP(0, self, maxPacketSize=maxPacketSize) 1802 2691 1803 2692 def datagramReceived(self, data, addr): 1804 2693 """ -
twisted/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 … … 150 153 151 154 return FileAuthority.__dict__['_lookup'](self, name, cls, type, timeout) 152 155 153 # shouldn't we just subclass? :P156 # shouldn't we just subclass? :P 154 157 155 158 lookupZone = FileAuthority.__dict__['lookupZone'] 156 159 … … 164 167 r.setdefault(str(rec.name).lower(), []).append(rec.payload) 165 168 166 169 def _ebZone(self, failure): 167 log.msg("Updating %s from %s failed during zone transfer" % (self.domain, self.primary)) 170 log.msg("Updating %s from %s failed during zone transfer" 171 % (self.domain, self.primary)) 168 172 log.err(failure) 169 173 170 174 def update(self): … … 175 179 176 180 def _ebTransferred(self, failure): 177 181 self.transferred = False 178 log.msg("Transferring %s from %s failed after zone transfer" % (self.domain, self.primary)) 182 log.msg("Transferring %s from %s failed after zone transfer" 183 % (self.domain, self.primary)) 179 184 log.err(failure) -
twisted/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 @author: Bob Novas 14 15 @since: 12.1 16 """ 17 18 import calendar, time 19 20 21 22 class SNA(object): 23 """ 24 implements RFC 1982 - DNS Serial Number Arithmetic 25 """ 26 SERIAL_BITS = 32 27 MODULOVAL = 2**SERIAL_BITS 28 HLFRNG = 2**(SERIAL_BITS-1) 29 MAXADD = (2**(SERIAL_BITS-1)-1) 30 31 32 def __init__(self, number): 33 self._number = int(number)%self.MODULOVAL 34 35 36 def __repr__(self): 37 return str(self._number) 38 39 40 def asInt(self): 41 """ 42 return an integer representing the object 43 """ 44 return self._number 45 46 47 def __eq__(self, sna2): 48 """ 49 define the equality operator 50 """ 51 return sna2._number == self._number 52 53 54 def __lt__(self, sna2): 55 """ 56 define the less than operator 57 """ 58 return ((self != sna2) and 59 ((self._number < sna2._number) and 60 ((sna2._number - self._number) < self.HLFRNG) or 61 (self._number > sna2._number) and 62 ((self._number - sna2._number) > self.HLFRNG))) 63 64 65 def __gt__(self, sna2): 66 """ 67 define the greater than operator 68 """ 69 return ((self != sna2) and 70 ((self._number < sna2._number) and 71 ((sna2._number - self._number) > self.HLFRNG) or 72 (self._number > sna2._number) and 73 ((self._number - sna2._number) < self.HLFRNG))) 74 75 76 def __le__(self, sna2): 77 """ 78 define the less than or equal operator 79 """ 80 return self == sna2 or self < sna2 81 82 83 def __ge__(self, sna2): 84 """ 85 define the greater than or equal operator 86 """ 87 return self == sna2 or self > sna2 88 89 90 def __add__(self, sna2): 91 """ 92 define the addition operator 93 """ 94 if sna2 <= SNA(self.MAXADD): 95 return SNA( (self._number + sna2._number)%self.MODULOVAL ) 96 else: 97 raise ArithmeticError 98 99 100 def __hash__(self): 101 """ 102 define a hash function 103 """ 104 return hash(self._number) 105 106 107 108 def max(snaList): 109 """ 110 takes a list of sna's from which it will pick the one 111 with the highest value 112 """ 113 if len(snaList) == 0: 114 return None 115 trialMax = snaList[0] 116 for s in snaList[1:]: 117 if not trialMax: 118 trialMax = s 119 elif s and s > trialMax: 120 trialMax = s 121 return trialMax 122 123 124 125 class DateSNA(SNA): 126 """ 127 implements DNS Serial Number Arithmetic 128 for dates 'YYYYMMDDHHMMSS' per RFC 4034 P3.1.5 129 """ 130 fmt = '%Y%m%d%H%M%S' 131 132 133 def __init__(self, utcDateTime=''): 134 """ 135 accept a UTC date/time string as YYMMDDHHMMSS 136 and convert it to seconds since the epoch 137 """ 138 if not utcDateTime: 139 utcDateTime = '19700101000000' 140 dtstruct = time.strptime(utcDateTime, DateSNA.fmt) 141 secondsSinceE = calendar.timegm(dtstruct) 142 super(DateSNA, self).__init__(secondsSinceE) 143 144 145 def __add__(self, sna2): 146 """ 147 define the addition operator 148 """ 149 if not isinstance(sna2, SNA): 150 return NotImplemented 151 152 if (sna2 <= SNA(self.MAXADD) and 153 (self._number + sna2._number < self.MODULOVAL)): 154 sna = SNA((self._number + sna2._number)%self.MODULOVAL) 155 return DateSNA.fromSNA(sna) 156 else: 157 raise ArithmeticError 158 159 160 def asDate(self): 161 """return a representation of the object as a date string""" 162 dtstruct = time.gmtime(self._number) 163 return time.strftime(DateSNA.fmt, dtstruct) 164 165 166 @classmethod 167 def fromSNA(cls, sna): 168 """ 169 create an DateSNA object from an SNA 170 """ 171 d = cls() 172 d._number = sna._number 173 return d 174 175 176 @classmethod 177 def fromInt(cls, i): 178 """ 179 create an DateSNA object from an int 180 """ 181 return cls.fromSNA(SNA(i)) 182 183 184 def __str__(self): 185 """ 186 return a string representation of the object 187 """ 188 return self.asDate() 189 -
twisted/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): … … 430 432 self.assertNotIn(protocol, resolver.connections) 431 433 432 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). 433 440 441 In addition, check that the message flag bits (DO, CD, RC) agree 442 with the flags set in the resolver. 443 444 @since: 12.1 445 """ 446 # make sure EDNS is enabled 447 self.assertTrue(resolver.dnssecConfig.ednsEnabled) 448 449 d = resolver._query(('example.com', 53), 450 [Query('foo.example.com',dns.A, dns.IN)], 451 30) 452 453 # A UDP port should have been started 454 portNumber, transport = reactor.udpPorts.popitem() 455 456 # and a DNS packet sent 457 [(packet, address)] = transport._sentPackets 458 459 msg = Message() 460 msg.fromStr(packet) 461 462 # the query should have an additional OPT Header with 463 # version == 0 and payload_size as defined by the resolver's 464 # dnssecConfig and DO should be set 465 self.assertEqual(len(msg.additional), 1) 466 additional = msg.additional[0] 467 payload = additional.payload 468 dnssecConfig = resolver.dnssecConfig 469 self.assertEqual(additional.type, dns.OPT) 470 self.assertEqual(payload.version, dnssecConfig.version) 471 self.assertEqual(payload.payload_size, dnssecConfig.maxUdpPktSz) 472 # payload.flags bit 15 is DO, should equal resolver.dnssecOk 473 self.assertEqual(not not(payload.flags & 0x8000), dnssecConfig.dnssecOk) 474 475 # the rest of the query should be as above also 476 self.assertEqual(msg.queries, [Query('foo.example.com', dns.A, dns.IN)]) 477 self.assertEqual(msg.answers, []) 478 self.assertEqual(msg.authority, []) 479 480 # the message header flags should be set as per the resolver's 481 # dnssecConfig settings 482 self.assertEqual(msg.chkDis, dnssecConfig.chkDis) 483 self.assertEqual(msg.recDes, dnssecConfig.recDes) 484 485 response = [] 486 d.addCallback(response.append) 487 self.assertEqual(response, []) 488 489 # Once a reply is received, the Deferred should fire. 490 # Make the flag bits in the message agree with what you asked for 491 del msg.queries[:] 492 msg.answer = 1 493 msg.answers.append(dns.RRHeader('foo.example.com', 494 payload=dns.Record_A('5.8.13.21'))) 495 # if you requested DO, say you got AD 496 msg.authData = dnssecConfig.dnssecOk 497 msg.chkDis = dnssecConfig.chkDis 498 msg.recDes = dnssecConfig.recDes 499 transport._protocol.datagramReceived(msg.toStr(), ('1.1.2.4', 1053)) 500 return response[0] 501 502 503 def test_dnssecEnabled(self): 504 """ 505 A query sent with DNSSEC Enabled has an additional OPT record with 506 DO set. Such a query returns a 4-tuple as a result, with the 4th 507 member of the tuple being the message with the header bits set as 508 set in the original query. 509 510 @since: 12.1 511 """ 512 # Create a resolver with EDNS0, max packet size = 4096, 513 # and dnssecOk, chkDis and recDes = True 514 maxPacketSize = 4096 515 dsc = DnssecConfig(ednsEnabled=True, 516 maxUdpPktSz=maxPacketSize, 517 dnssecOk=True, # DO 518 chkDis=True, # CD 519 recDes=True) # RC 520 521 reactor = MemoryReactor() 522 resolver = client.Resolver(servers=[('example.com', 53)], 523 reactor=reactor, 524 dnssecConfig=dsc) 525 526 message = self._edns0ConfigurationTest(reactor, resolver) 527 528 # check that a resolver with dnssecOk returns a 4-tuple with the 529 # header set as in the query 530 answer, authority, additional, message = resolver.filterAnswers(message) 531 self.assertEqual(answer, [dns.RRHeader('foo.example.com', 532 payload=dns.Record_A('5.8.13.21', ttl=0))]) 533 self.assertEqual(authority, []) 534 self.assertEqual(additional, []) 535 self.assertIsInstance(message, dns.Message) 536 self.assertTrue(message.authData) 537 self.assertTrue(message.chkDis) 538 self.assertTrue(message.recDes) 539 540 541 def test_dnssecDisabled(self): 542 """ 543 A query sent with DNSSEC Disabled but EDNS enabled has an additional 544 OPT record with DO clear. Such a query returns a 3-tuple as a result. 545 """ 546 547 # Create a resolver with EDNS0, max packet size = 4096, 548 # and dnssecOk = False, but recDes = True 549 maxPacketSize = 4096 550 dsc = DnssecConfig(ednsEnabled=True, 551 maxUdpPktSz=maxPacketSize, 552 dnssecOk=False, # not DO 553 recDes=True) # RC 554 555 reactor = MemoryReactor() 556 resolver = client.Resolver(servers=[('example.com', 53)], 557 reactor=reactor, 558 dnssecConfig=dsc) 559 560 message = self._edns0ConfigurationTest(reactor, resolver) 561 562 # check that a resolver with dnssecOk == False returns a 3-tuple 563 # containing the right stuff. 564 # Note - no access to header info in this case 565 answer, authority, additional = resolver.filterAnswers(message) 566 self.assertEqual(answer, 567 [dns.RRHeader('foo.example.com', 568 payload=dns.Record_A('5.8.13.21', ttl=0))]) 569 self.assertEqual(authority, []) 570 self.assertEqual(additional, []) 571 572 434 573 class ClientTestCase(unittest.TestCase): 435 574 436 575 def setUp(self): … … 658 797 return d 659 798 660 799 800 def test_lookupDNSKey(self): 801 """ 802 See L{test_lookupAddress} 803 """ 804 d = client.lookupDNSKey(self.hostname) 805 d.addCallback(self.checkResult, dns.DNSKEY) 806 return d 807 808 809 def test_lookupDS(self): 810 """ 811 See L{test_lookupAddress} 812 813 @since: 12.1 814 """ 815 d = client.lookupDS(self.hostname) 816 d.addCallback(self.checkResult, dns.DS) 817 return d 818 819 820 def test_lookupNSEC(self): 821 """ 822 See L{test_lookupAddress} 823 824 @since: 12.1 825 """ 826 d = client.lookupNSEC(self.hostname) 827 d.addCallback(self.checkResult, dns.NSEC) 828 return d 829 830 831 def test_lookupNSEC3(self): 832 """ 833 See L{test_lookupAddress} 834 835 @since: 12.1 836 """ 837 d = client.lookupNSEC3(self.hostname) 838 d.addCallback(self.checkResult, dns.NSEC3) 839 return d 840 841 842 def test_lookupNSEC3Param(self): 843 """ 844 See L{test_lookupAddress} 845 846 @since: 12.1 847 """ 848 d = client.lookupNSEC3Param(self.hostname) 849 d.addCallback(self.checkResult, dns.NSEC3PARAM) 850 return d 851 852 853 def test_lookupRRSIG(self): 854 """ 855 See L{test_lookupAddress} 856 857 @since: 12.1 858 """ 859 d = client.lookupRRSIG(self.hostname) 860 d.addCallback(self.checkResult, dns.RRSIG) 861 return d 862 863 661 864 class ThreadedResolverTests(unittest.TestCase): 662 865 """ 663 866 Tests for L{client.ThreadedResolver}. -
twisted/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"] 195 sigs = ["Qm12VZVaZgKS0/DZx35SGECDwPiTTf3ngChb7OkgSv5iupVmJGhPWudm " 196 "/18qBSXKyv9hxMlEXFFgpBieNqLfSBkP1bwKnlqPfr1Hx7ctDwDUpkT3 " 197 "cS8u/ms9yo3Fu1ybpO4Hfsb1HbA2N3zzQnjWKnyk26AAQSz8KgjNTFzD " 198 "tJM=", 199 "ZH2kahMD1g2WOieIotAcBwB0e/o30Zq6YR//M/xwP1ktkYuclmcR56iv " 200 "XiR3QFWqmN5Xz3YpgmM4tZkjIeSMp2doYa7XYORZ7OpzG7oyfo8IoXxc " 201 "j1VGDeAn1CeNCpBtoSGapRABG1gjY7oeRj/smPQPp2Gkf79+WZfuzRom " 202 "/t4=", 203 "AZpaboyNQAmbnBO1K66QmZ0c+VCdY/wu9QpEdRnMpnIOLPD28pNVu6hk " 204 "GQMz6eg5WYkPYDdJK+1D/oyAQkDmRgn10+O9EdeFDyLqYqq/htEAvDm4 " 205 "CziMSOpD/mkg1bSWCZ2mdln/GBk8WooCeeM7LEHmRjmHMMj0xb6N4SKa " 206 "MEc=", 207 "AwEAAbi5VQa3x+R3WQouBDNts+ZX2zIKZNoj9pzl7ew446kI/2omv3j6 " 208 "c/4RQ6VneYE3mK7r0fFIKhVagmiRroFO1rRUJ8sVidssZ35CldE0sju+ " 209 "E7wymVg3tV+ZUUO/+5v6Sfj+tw3rlp6eKqm7EGKKM88t+KuXiGYMu0Vw " 210 "Rm9OUO1n", 211 "AwEAAbmTL+kuV45kAxGN//iBKz93Y6lutgxoptp+I1+PZZMsBkhm/dZj " 212 "q57040Pz/Hr3f2zQX7z6fFu7/Ml3MHPH1eQDiVXDvOkeNq2x4IbCO7x+ " 213 "0p6bGYj4fw/tEfh/8dUzyzvMwfuAMsOvXza8Kh+UP4jvFc95cUuGgYus " 214 "uEjUOp40PsL7EtYvAks3UssA6/OZP4w/1Z5m/VFx4PzgY0dkEuc=", 215 "VGPxa8A81eV1dtUxVhz9b9Jsp6FF4M5H6J0QhzbNCUTHTHjLNR2VHYfE " 216 "fM+Akwo3/qKq3D6vzTfzqtyPAXP8CmGfdD8hfv0s7Hae9c7Is8usdlrk " 217 "ZpoXEFMW+YVG8G9OieYViq6tBIpUvKgMVZ+oXKo63KJ/tC/yBW0H0VQP " 218 "YwdzZ3ZvYRDmZDvrXoX7T0YNU+0HYHnb7g7nUECIJ/4HHg==", 219 "M+u8Uxm2y2Q142qED0kVNIiSOHBkfiU3xBhMq9H4T/K+oeC7Y81HIOFE " 220 "h9k6ZS/Ba5X0/Fr1yyq5Z/+0/Q845Kya8Lmkp/ikJVe/9id2TC2hoffp " 221 "Z9pbZRjIeBTAvdTboGmGuqG/ljnDLJrJpoF6g8g6fHR9eekIWis8LJ55 " 222 "Y1k="] 223 type_bitmaps = ["A MX RRSIG NSEC TYPE1234", 224 "AAAA NS CNAME MX TXT RRSIG NSEC3 DNAME", 225 "NSEC3 A AAAA RRSIG DS NS " 226 "TYPE5000 TYPE1000 TYPE2000 TYPE3000 TYPE4000", 227 None] 192 228 193 229 def testName(self): 194 230 for n in self.names: … … 276 312 self.assertEqual(result.string, n) 277 313 278 314 315 def test_Sigstr(self): 316 """ 317 Test L{dns.Sigstr} encode and decode. 318 319 @since: 12.1 320 """ 321 for s in self.sigs: 322 # encode the signature/key 323 f = StringIO() 324 dns.Sigstr(s).encode(f) 325 l = f.tell() 326 327 # decode the signature/key 328 f.seek(0, 0) 329 result = dns.Sigstr() 330 result.decode(f,l) 331 # spaces are free, and dig sticks them in 332 self.assertEqual(result.string, s.replace(' ', '')) 333 334 335 def test_TypeBitmaps(self): 336 """ 337 Test L{dns.TypeBitmaps} encode and decode. 338 339 @since: 12.1 340 """ 341 typeRegex = re.compile('TYPE(\d+)') 342 343 for b in self.type_bitmaps: 344 # encode the type_bitmaps 345 f = StringIO() 346 dns.TypeBitmaps(b).encode(f) 347 l = f.tell() 348 349 # decode the type_bitmaps 350 f.seek(0, 0) 351 result = dns.TypeBitmaps() 352 result.decode(f,l) 353 354 def mnuVal(mnu): 355 mnuVal = dns.REV_TYPES.get(mnu, None) 356 if not mnuVal: 357 m = typeRegex.match(mnu) 358 if m.groups(): 359 mnuVal = int(m.group(1)) 360 assert mnuVal < 65536 361 else: 362 log.err("can't parse %s in %s" % (mnu, self.string, )) 363 mnuVal = 0 364 return mnuVal 365 366 def sorttok(string): 367 if not string: 368 return '' 369 370 toks = string.split(' ') 371 toks.sort(key = mnuVal) 372 return ' '.join(toks) 373 374 self.assertEqual(result.type_bitmaps, sorttok(b)) 375 376 279 377 def test_NAPTR(self): 280 378 """ 281 379 Test L{dns.Record_NAPTR} encode and decode. … … 325 423 msg = dns.Message() 326 424 msg.fromStr( 327 425 '\x01\x00' # Message ID 328 '\x00' # answer bit, opCode nibble, auth bit, trunc bit, recursive bit329 '\x00' # recursion bit, empty bit, empty bit, empty bit, response code nibble426 '\x00' # answer bit, opCode nibble, auth, trunc, recursive bits 427 '\x00' # recursion bit, 3 empty bits, response code nibble 330 428 '\x00\x00' # number of queries 331 429 '\x00\x00' # number of answers 332 430 '\x00\x00' # number of authorities … … 439 537 Initialize the controller: create a list of messages. 440 538 """ 441 539 self.messages = [] 540 self.dnssecConfig = common.DnssecConfig() 442 541 443 542 444 543 def messageReceived(self, msg, proto, addr): … … 893 992 repr(dns.UnknownRecord("foo\x1fbar", 12)), 894 993 "<UNKNOWN data='foo\\x1fbar' ttl=12>") 895 994 995 def test_dnskey(self): 996 """ 997 The repr of a L{dns.DNSKEY} instance includes the flags, protocol, 998 algo, pub_key and ttl fields of the record. 999 1000 @since: 12.1 1001 """ 1002 self.assertEqual( 1003 repr(dns.Record_DNSKEY(10, 20, 30, "foo\x1fbar", ttl=20)), 1004 "<DNSKEY flags=10 protocol=20 algo=30 pub_key=foo\x1fbar ttl=20>") 896 1005 1006 def test_ds(self): 1007 """ 1008 The repr of a L{dns.DS} instance includes the key_tag, algo, digest_type, 1009 digest and ttl fields of the record. 1010 1011 @since: 12.1 1012 """ 1013 self.assertEqual( 1014 repr(dns.Record_DS(11, 22, 33, "foo\x1fbar1", ttl=21)), 1015 "<DS key_tag=11 algo=22 digest_type=33 digest=foo\x1fbar1 ttl=21>") 897 1016 1017 def test_nsec(self): 1018 """ 1019 The repr of a L{dns.NSEC} instance includes the nxt_name, type_bitmaps 1020 and ttl fields of the record. 1021 1022 @since: 12.1 1023 """ 1024 self.assertEqual( 1025 repr(dns.Record_NSEC('bob', "\x1fabcd", ttl=31)), 1026 "<NSEC nxt_name=bob type_bitmaps=\x1fabcd ttl=31>") 1027 1028 def test_nsec3param(self): 1029 """ 1030 The repr of a L{dns.NSEC3PARAM} instance includes the hash_algo, flags, 1031 iterations, salt and ttl fields of the record. 1032 1033 @since: 12.1 1034 """ 1035 self.assertEqual( 1036 repr(dns.Record_NSEC3PARAM(1, 2, 3, '\x12\x34', ttl=31)), 1037 "<NSEC3 hash_algo=1 flags=2 iterations=3 salt=\x12\x34 ttl=31>") 1038 1039 def test_nsec3(self): 1040 """ 1041 The repr of a L{dns.NSEC3} instance includes the hash_algo, flags, 1042 iterations, salt, nxt_hash_owner_name, type_bitmaps and ttl fields 1043 of the record. 1044 1045 @since: 12.1 1046 """ 1047 self.assertEqual( 1048 repr(dns.Record_NSEC3(1, 2, 3, '\x12\x34', 'bob', 1049 "\x1fabcd", ttl=31)), 1050 "<NSEC3 hash_algo=1 flags=2 iterations=3 " 1051 "salt=\x12\x34 nxt_hash_owner_name=bob " 1052 "type_bitmaps=\x1fabcd ttl=31>") 1053 1054 def test_opt(self): 1055 """ 1056 The repr of a L{dns.OPT} instance includes the payload_size, dnssecOk 1057 flag, and version fields of the record. 1058 (The OPT record has no ttl field.) 1059 1060 @since: 12.1 1061 """ 1062 self.assertEqual( 1063 repr(dns.Record_OPT(payload_size=1492, dnssecOk=1, version=0)), 1064 "<OPT payload_size=1492 flags=0x8000 version=0>") 1065 1066 def test_rrsig(self): 1067 """ 1068 The repr of a L{dns.RRSIG} instance includes the algo, labels, 1069 original_ttl sig_expiration, sig_inception, key_tag, signers_name, 1070 signature and ttl fields of the record. 1071 1072 @since: 12.1 1073 """ 1074 self.assertEqual( 1075 repr(dns.Record_RRSIG(type_covered=dns.A, 1076 algo=2, 1077 labels=3, 1078 original_ttl=30, 1079 sig_expiration='20110101123456', 1080 sig_inception= '20110202112233', 1081 key_tag=60, 1082 signers_name='bob', 1083 signature='\x12\x34sig', 1084 ttl=70)), 1085 "<RRSIG type_covered=1 algo=2 labels=3 original_ttl=30" 1086 " sig_expiration=20110101123456 sig_inception=20110202112233 key_tag=60" 1087 " signers_name=bob signature=\x12\x34sig ttl=70>") 1088 898 1089 class _Equal(object): 899 1090 """ 900 1091 A class the instances of which are equal to anything and everything. … … 961 1152 cls('example.com', 123), 962 1153 cls('example.org', 123)) 963 1154 1155 def test_optheader(self): 1156 """ 1157 Two OptHeader instances comapare equal iff the have the same 1158 (Record_OPT) payload and auth bit. 1159 """ 1160 self._equalityTest( 1161 dns.OPTHeader(payload=dns.Record_OPT(payload_size=1024, 1162 dnssecOk=True, 1163 version=0, 1164 ttl=30)), 1165 dns.OPTHeader(payload=dns.Record_OPT(payload_size=1024, 1166 dnssecOk=True, 1167 version=0, 1168 ttl=30)), 1169 dns.OPTHeader(payload=dns.Record_OPT(payload_size=1492, 1170 dnssecOk=False, 1171 version=0, 1172 ttl=40), auth=True)) 964 1173 965 1174 def test_rrheader(self): 966 1175 """ … … 968 1177 the same name, type, class, time to live, payload, and authoritative 969 1178 bit. 970 1179 """ 1180 aRec = dns.Record_A('1.2.3.4') 1181 971 1182 # Vary the name 972 1183 self._equalityTest( 973 dns.RRHeader('example.com', payload= dns.Record_A('1.2.3.4')),974 dns.RRHeader('example.com', payload= dns.Record_A('1.2.3.4')),975 dns.RRHeader('example.org', payload= dns.Record_A('1.2.3.4')))1184 dns.RRHeader('example.com', payload=aRec), 1185 dns.RRHeader('example.com', payload=aRec), 1186 dns.RRHeader('example.org', payload=aRec)) 976 1187 977 1188 # Vary the payload 978 1189 self._equalityTest( 979 dns.RRHeader('example.com', payload= dns.Record_A('1.2.3.4')),980 dns.RRHeader('example.com', payload= dns.Record_A('1.2.3.4')),1190 dns.RRHeader('example.com', payload=aRec), 1191 dns.RRHeader('example.com', payload=aRec), 981 1192 dns.RRHeader('example.com', payload=dns.Record_A('1.2.3.5'))) 982 1193 983 1194 # Vary the type. Leave the payload as None so that we don't have to … … 989 1200 990 1201 # Probably not likely to come up. Most people use the internet. 991 1202 self._equalityTest( 992 dns.RRHeader('example.com', cls=dns.IN, payload= dns.Record_A('1.2.3.4')),993 dns.RRHeader('example.com', cls=dns.IN, payload= dns.Record_A('1.2.3.4')),994 dns.RRHeader('example.com', cls=dns.CS, payload= dns.Record_A('1.2.3.4')))1203 dns.RRHeader('example.com', cls=dns.IN, payload=aRec), 1204 dns.RRHeader('example.com', cls=dns.IN, payload=aRec), 1205 dns.RRHeader('example.com', cls=dns.CS, payload=aRec)) 995 1206 996 1207 # Vary the ttl 997 1208 self._equalityTest( 998 dns.RRHeader('example.com', ttl=60, payload= dns.Record_A('1.2.3.4')),999 dns.RRHeader('example.com', ttl=60, payload= dns.Record_A('1.2.3.4')),1000 dns.RRHeader('example.com', ttl=120, payload= dns.Record_A('1.2.3.4')))1209 dns.RRHeader('example.com', ttl=60, payload=aRec), 1210 dns.RRHeader('example.com', ttl=60, payload=aRec), 1211 dns.RRHeader('example.com', ttl=120, payload=aRec)) 1001 1212 1002 1213 # Vary the auth bit 1003 1214 self._equalityTest( 1004 dns.RRHeader('example.com', auth=1, payload= dns.Record_A('1.2.3.4')),1005 dns.RRHeader('example.com', auth=1, payload= dns.Record_A('1.2.3.4')),1006 dns.RRHeader('example.com', auth=0, payload= dns.Record_A('1.2.3.4')))1215 dns.RRHeader('example.com', auth=1, payload=aRec), 1216 dns.RRHeader('example.com', auth=1, payload=aRec), 1217 dns.RRHeader('example.com', auth=0, payload=aRec)) 1007 1218 1008 1219 1009 1220 def test_ns(self): … … 1483 1694 dns.UnknownRecord('foo', ttl=10), 1484 1695 dns.UnknownRecord('foo', ttl=10), 1485 1696 dns.UnknownRecord('foo', ttl=100)) 1697 1698 def test_rrsig(self): 1699 """ 1700 L(dns.RRSIG) instances compare equal iff they have the same 1701 type_covered, algo, labels, original_ttl, sig_expiration, sig_inception, 1702 key_tag, signers_name, signature, and ttl 1703 1704 @since: 12.1 1705 """ 1706 self._equalityTest( 1707 dns.Record_RRSIG(type_covered=dns.A), 1708 dns.Record_RRSIG(type_covered=dns.A), 1709 dns.Record_RRSIG(type_covered=dns.AAAA)) 1710 self._equalityTest( 1711 dns.Record_RRSIG(algo=1), 1712 dns.Record_RRSIG(algo=1), 1713 dns.Record_RRSIG(algo=2)) 1714 self._equalityTest( 1715 dns.Record_RRSIG(labels=3), 1716 dns.Record_RRSIG(labels=3), 1717 dns.Record_RRSIG(labels=4)) 1718 self._equalityTest( 1719 dns.Record_RRSIG(original_ttl=5), 1720 dns.Record_RRSIG(original_ttl=5), 1721 dns.Record_RRSIG(original_ttl=6)) 1722 self._equalityTest( 1723 dns.Record_RRSIG(sig_expiration='20110101000000'), 1724 dns.Record_RRSIG(sig_expiration='20110101000000'), 1725 dns.Record_RRSIG(sig_expiration='20110101000001')) 1726 self._equalityTest( 1727 dns.Record_RRSIG(sig_inception='20120101000000'), 1728 dns.Record_RRSIG(sig_inception='20120101000000'), 1729 dns.Record_RRSIG(sig_inception='20120101000001')) 1730 self._equalityTest( 1731 dns.Record_RRSIG(key_tag=11), 1732 dns.Record_RRSIG(key_tag=11), 1733 dns.Record_RRSIG(key_tag=12)) 1734 self._equalityTest( 1735 dns.Record_RRSIG(signers_name='bob'), 1736 dns.Record_RRSIG(signers_name='bob'), 1737 dns.Record_RRSIG(signers_name='joe')) 1738 self._equalityTest( 1739 dns.Record_RRSIG(signature='abcdef'), 1740 dns.Record_RRSIG(signature='abcdef'), 1741 dns.Record_RRSIG(signature='abcdefg')) 1742 self._equalityTest( 1743 dns.Record_RRSIG(ttl=10), 1744 dns.Record_RRSIG(ttl=10), 1745 dns.Record_RRSIG(ttl=20)) 1746 1747 def test_ds(self): 1748 """ 1749 L(dns.DS) instances compare equal iff they have the same 1750 key_tag, algo, digest_type, digest and ttl 1751 1752 @since: 12.1 1753 """ 1754 self._equalityTest( 1755 dns.Record_DS(key_tag=1), 1756 dns.Record_DS(key_tag=1), 1757 dns.Record_DS(key_tag=2)) 1758 self._equalityTest( 1759 dns.Record_DS(algo=3), 1760 dns.Record_DS(algo=3), 1761 dns.Record_DS(algo=4)) 1762 self._equalityTest( 1763 dns.Record_DS(digest_type=5), 1764 dns.Record_DS(digest_type=5), 1765 dns.Record_DS(digest_type=6)) 1766 self._equalityTest( 1767 dns.Record_DS(digest='abcdef-digest'), 1768 dns.Record_DS(digest='abcdef-digest'), 1769 dns.Record_DS(digest='abcdef-digest-f')) 1770 self._equalityTest( 1771 dns.Record_DS(ttl=10), 1772 dns.Record_DS(ttl=10), 1773 dns.Record_DS(ttl=20)) 1774 1775 def test_dnskey(self): 1776 """ 1777 L(dns.DNSKEY) instances compare equal iff they have the same 1778 flags, protocol, algo, pub_key and ttl 1779 1780 @since: 12.1 1781 """ 1782 self._equalityTest( 1783 dns.Record_DNSKEY(flags=1), 1784 dns.Record_DNSKEY(flags=1), 1785 dns.Record_DNSKEY(flags=2)) 1786 self._equalityTest( 1787 dns.Record_DNSKEY(protocol=3), 1788 dns.Record_DNSKEY(protocol=3), 1789 dns.Record_DNSKEY(protocol=4)) 1790 self._equalityTest( 1791 dns.Record_DNSKEY(algo=5), 1792 dns.Record_DNSKEY(algo=5), 1793 dns.Record_DNSKEY(algo=6)) 1794 self._equalityTest( 1795 dns.Record_DNSKEY(pub_key='abcdef-digest'), 1796 dns.Record_DNSKEY(pub_key='abcdef-digest'), 1797 dns.Record_DNSKEY(pub_key='abcdef-digest-f')) 1798 self._equalityTest( 1799 dns.Record_DNSKEY(ttl=10), 1800 dns.Record_DNSKEY(ttl=10), 1801 dns.Record_DNSKEY(ttl=20)) 1802 1803 def test_nsec(self): 1804 """ 1805 L(dns.DNSKEY) instances compare equal iff they have the same 1806 nxt_name, type_bitmaps and ttl 1807 1808 @since: 12.1 1809 """ 1810 self._equalityTest( 1811 dns.Record_NSEC(nxt_name="example.com"), 1812 dns.Record_NSEC(nxt_name="example.com"), 1813 dns.Record_NSEC(nxt_name="a.example.com")) 1814 self._equalityTest( 1815 dns.Record_NSEC(type_bitmaps="A AAAA NS NSEC3"), 1816 dns.Record_NSEC(type_bitmaps="A AAAA NS NSEC3"), 1817 dns.Record_NSEC(type_bitmaps="A AAAA NS NSEC3 RRSIG")) 1818 self._equalityTest( 1819 dns.Record_NSEC(ttl=5), 1820 dns.Record_NSEC(ttl=5), 1821 dns.Record_NSEC(ttl=6)) 1822 1823 def test_nsec3param(self): 1824 """ 1825 L(dns.DNSKEY) instances compare equal iff they have the same 1826 hash_algo, flags, iterations, salt, nxt_hash_owner_name, type_bitmaps and ttl 1827 1828 @since: 12.1 1829 """ 1830 self._equalityTest( 1831 dns.Record_NSEC3PARAM(hash_algo=1), 1832 dns.Record_NSEC3PARAM(hash_algo=1), 1833 dns.Record_NSEC3PARAM(hash_algo=2)) 1834 self._equalityTest( 1835 dns.Record_NSEC3PARAM(flags=1), 1836 dns.Record_NSEC3PARAM(flags=1), 1837 dns.Record_NSEC3PARAM(flags=2)) 1838 self._equalityTest( 1839 dns.Record_NSEC3PARAM(iterations=5), 1840 dns.Record_NSEC3PARAM(iterations=5), 1841 dns.Record_NSEC3PARAM(iterations=6)) 1842 self._equalityTest( 1843 dns.Record_NSEC3PARAM(salt="abcdef"), 1844 dns.Record_NSEC3PARAM(salt="abcdef"), 1845 dns.Record_NSEC3PARAM(salt="abcdefg")) 1846 self._equalityTest( 1847 dns.Record_NSEC3PARAM(ttl=5), 1848 dns.Record_NSEC3PARAM(ttl=5), 1849 dns.Record_NSEC3PARAM(ttl=6)) 1850 1851 def test_nsec3(self): 1852 """ 1853 L(dns.DNSKEY) instances compare equal iff they have the same 1854 hash_algo, flags, iterations, salt, nxt_hash_owner_name, type_bitmaps 1855 and ttl 1856 1857 @since: 12.1 1858 """ 1859 self._equalityTest( 1860 dns.Record_NSEC3(hash_algo=1), 1861 dns.Record_NSEC3(hash_algo=1), 1862 dns.Record_NSEC3(hash_algo=2)) 1863 self._equalityTest( 1864 dns.Record_NSEC3(flags=1), 1865 dns.Record_NSEC3(flags=1), 1866 dns.Record_NSEC3(flags=2)) 1867 self._equalityTest( 1868 dns.Record_NSEC3(iterations=5), 1869 dns.Record_NSEC3(iterations=5), 1870 dns.Record_NSEC3(iterations=6)) 1871 self._equalityTest( 1872 dns.Record_NSEC3(salt="abcdef"), 1873 dns.Record_NSEC3(salt="abcdef"), 1874 dns.Record_NSEC3(salt="abcdefg")) 1875 self._equalityTest( 1876 dns.Record_NSEC3(nxt_hash_owner="example.com"), 1877 dns.Record_NSEC3(nxt_hash_owner="example.com"), 1878 dns.Record_NSEC3(nxt_hash_owner="a.example.com")) 1879 self._equalityTest( 1880 dns.Record_NSEC3(type_bitmaps="A AAAA NS NSEC3"), 1881 dns.Record_NSEC3(type_bitmaps="A AAAA NS NSEC3"), 1882 dns.Record_NSEC3(type_bitmaps="A AAAA NS NSEC3 RRSIG")) 1883 self._equalityTest( 1884 dns.Record_NSEC3(ttl=5), 1885 dns.Record_NSEC3(ttl=5), 1886 dns.Record_NSEC3(ttl=6)) 1887 1888 -
twisted/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" 104 "/K+oeC7Y81HIOFEh9k6ZS/Ba5X0/Fr1yyq5Z/+0/Q" 105 "845Kya8Lmkp/ikJVe/9id2TC2hoffpZ9pbZRjIeBT" 106 "AvdTboGmGuqG/ljnDLJrJpoF6g8g6fHR9eekIWis8" 107 "LJ55Y1k=" 108 )], 102 109 'http.tcp.test-domain.com': [ 103 110 dns.Record_SRV(257, 16383, 43690, 'some.other.place.fool') 104 111 ], 105 112 'host.test-domain.com': [ 106 113 dns.Record_A('123.242.1.5'), 107 114 dns.Record_A('0.255.0.255'), 115 dns.Record_RRSIG(dns.A, 5, 3, 86400, 116 '20120101000000', '20120201000000', 117 2642, 'test-domain.com', 118 "M+u8Uxm2y2Q142qED0kVNIiSOHBkfiU3xBhMq9H4T/K" 119 "+oeC7Y81HIOFEh9k6ZS/Ba5X0/Fr1yyq5Z/+0/Q845K" 120 "ya8Lmkp/ikJVe/9id2TC2hoffpZ9pbZRjIeBTAvdTbo" 121 "GmGuqG/ljnDLJrJpoF6g8g6fHR9eekIWis8LJ55Y1k=") 108 122 ], 109 123 'host-two.test-domain.com': [ 110 124 # … … 224 238 """Test DNS 'A' record queries with multiple answers""" 225 239 return self.namesTest( 226 240 self.resolver.lookupAddress('host.test-domain.com'), 227 [dns.Record_A('123.242.1.5', ttl=19283784), dns.Record_A('0.255.0.255', ttl=19283784)] 241 [dns.Record_A('123.242.1.5', ttl=19283784), 242 dns.Record_A('0.255.0.255', ttl=19283784)] 228 243 ) 229 244 230 245 … … 232 247 """Test DNS 'A' record queries with edge cases""" 233 248 return self.namesTest( 234 249 self.resolver.lookupAddress('host-two.test-domain.com'), 235 [dns.Record_A('255.255.255.254', ttl=19283784), dns.Record_A('0.0.0.0', ttl=19283784)] 250 [dns.Record_A('255.255.255.254', ttl=19283784), 251 dns.Record_A('0.0.0.0', ttl=19283784)] 236 252 ) 237 253 238 254 … … 264 280 """Test DNS 'HINFO' record queries""" 265 281 return self.namesTest( 266 282 self.resolver.lookupHostInfo('test-domain.com'), 267 [dns.Record_HINFO(os='Linux', cpu='A Fast One, Dontcha know', ttl=19283784)] 283 [dns.Record_HINFO(os='Linux', cpu='A Fast One, Dontcha know', 284 ttl=19283784)] 268 285 ) 269 286 270 287 def testPTR(self): … … 286 303 """Test additional processing for CNAME records""" 287 304 return self.namesTest( 288 305 self.resolver.lookupAddress('cname.test-domain.com'), 289 [dns.Record_CNAME('test-domain.com', ttl=19283784), dns.Record_A('127.0.0.1', ttl=19283784)] 306 [dns.Record_CNAME('test-domain.com', ttl=19283784), 307 dns.Record_A('127.0.0.1', ttl=19283784)] 290 308 ) 291 309 292 310 def testMB(self): … … 317 335 """Test DNS 'MINFO' record queries""" 318 336 return self.namesTest( 319 337 self.resolver.lookupMailboxInfo('test-domain.com'), 320 [dns.Record_MINFO(rmailbx='r mail box', emailbx='e mail box', ttl=19283784)] 338 [dns.Record_MINFO(rmailbx='r mail box', emailbx='e mail box', 339 ttl=19283784)] 321 340 ) 322 341 323 342 … … 325 344 """Test DNS 'SRV' record queries""" 326 345 return self.namesTest( 327 346 self.resolver.lookupService('http.tcp.test-domain.com'), 328 [dns.Record_SRV(257, 16383, 43690, 'some.other.place.fool', ttl=19283784)] 347 [dns.Record_SRV(257, 16383, 43690, 'some.other.place.fool', 348 ttl=19283784)] 329 349 ) 330 350 331 351 def testAFSDB(self): 332 352 """Test DNS 'AFSDB' record queries""" 333 353 return self.namesTest( 334 354 self.resolver.lookupAFSDatabase('test-domain.com'), 335 [dns.Record_AFSDB(subtype=1, hostname='afsdb.test-domain.com', ttl=19283784)] 355 [dns.Record_AFSDB(subtype=1, hostname='afsdb.test-domain.com', 356 ttl=19283784)] 336 357 ) 337 358 338 359 … … 340 361 """Test DNS 'RP' record queries""" 341 362 return self.namesTest( 342 363 self.resolver.lookupResponsibility('test-domain.com'), 343 [dns.Record_RP(mbox='whatever.i.dunno', txt='some.more.text', ttl=19283784)] 364 [dns.Record_RP(mbox='whatever.i.dunno', txt='some.more.text', 365 ttl=19283784)] 344 366 ) 345 367 346 368 … … 348 370 """Test DNS 'TXT' record queries""" 349 371 return self.namesTest( 350 372 self.resolver.lookupText('test-domain.com'), 351 [dns.Record_TXT('A First piece of Text', 'a SecoNd piece', ttl=19283784), 352 dns.Record_TXT('Some more text, haha! Yes. \0 Still here?', ttl=19283784)] 373 [dns.Record_TXT('A First piece of Text', 'a SecoNd piece', 374 ttl=19283784), 375 dns.Record_TXT('Some more text, haha! Yes. \0 Still here?', 376 ttl=19283784)] 353 377 ) 354 378 355 379 … … 359 383 """ 360 384 return self.namesTest( 361 385 self.resolver.lookupSenderPolicy('test-domain.com'), 362 [dns.Record_SPF('v=spf1 mx/30 mx:example.org/30 -all', ttl=19283784), 363 dns.Record_SPF('v=spf1 +mx a:\0colo', '.example.com/28 -all not valid', ttl=19283784)] 386 [dns.Record_SPF('v=spf1 mx/30 mx:example.org/30 -all', 387 ttl=19283784), 388 dns.Record_SPF('v=spf1 +mx a:\0colo', 389 '.example.com/28 -all not valid', 390 ttl=19283784)] 364 391 ) 365 392 366 393 … … 368 395 """Test DNS 'WKS' record queries""" 369 396 return self.namesTest( 370 397 self.resolver.lookupWellKnownServices('test-domain.com'), 371 [dns.Record_WKS('12.54.78.12', socket.IPPROTO_TCP, '\x12\x01\x16\xfe\xc1\x00\x01', ttl=19283784)] 398 [dns.Record_WKS('12.54.78.12', socket.IPPROTO_TCP, 399 '\x12\x01\x16\xfe\xc1\x00\x01', ttl=19283784)] 372 400 ) 373 401 374 402 … … 381 409 dns.Record_A('1.2.3.4', ttl='1S'), 382 410 dns.Record_NS('ns1.domain', ttl='2M'), 383 411 dns.Record_NS('ns2.domain', ttl='3H'), 384 dns.Record_SRV(257, 16383, 43690, 'some.other.place.fool', ttl='4D')] 412 dns.Record_SRV(257, 16383, 43690, 'some.other.place.fool', 413 ttl='4D')] 385 414 ) 386 415 387 416 … … 389 418 """Test DNS 'AAAA' record queries (IPv6)""" 390 419 return self.namesTest( 391 420 self.resolver.lookupIPV6Address('test-domain.com'), 392 [dns.Record_AAAA('AF43:5634:1294:AFCB:56AC:48EF:34C3:01FF', ttl=19283784)] 421 [dns.Record_AAAA('AF43:5634:1294:AFCB:56AC:48EF:34C3:01FF', 422 ttl=19283784)] 393 423 ) 394 424 395 425 def testA6(self): … … 398 428 self.resolver.lookupAddress6('test-domain.com'), 399 429 [dns.Record_A6(0, 'ABCD::4321', '', ttl=19283784), 400 430 dns.Record_A6(12, '0:0069::0', 'some.network.tld', ttl=19283784), 401 dns.Record_A6(8, '0:5634:1294:AFCB:56AC:48EF:34C3:01FF', 'tra.la.la.net', ttl=19283784)] 431 dns.Record_A6(8, '0:5634:1294:AFCB:56AC:48EF:34C3:01FF', 432 'tra.la.la.net', ttl=19283784)] 402 433 ) 403 434 404 435 … … 407 438 Test DNS 'AXFR' queries (Zone transfer) 408 439 """ 409 440 default_ttl = soa_record.expire 410 results = [copy.copy(r) for r in reduce(operator.add, test_domain_com.records.values())] 441 results = [copy.copy(r) 442 for r in reduce(operator.add, 443 test_domain_com.records.values())] 411 444 for r in results: 412 445 if r.ttl is None: 413 446 r.ttl = default_ttl … … 435 468 "!^.*$!sip:information@domain.tld!", 436 469 ttl=19283784)]) 437 470 471 def test_DNSKEY(self): 472 """ 473 Test DNS 'DNSKEY' record queries. 474 475 @since: 12.1 476 """ 477 return self.namesTest( 478 self.resolver.lookupDNSKey('test-domain.com'), 479 [dns.Record_DNSKEY(0x10, 3, 5, 480 "M+u8Uxm2y2Q142qED0kVNIiSOHBkfiU3xBhMq9" 481 "H4T/K+oeC7Y81HIOFEh9k6ZS/Ba5X0/Fr1yyq5" 482 "Z/+0/Q845Kya8Lmkp/ikJVe/9id2TC2hoffpZ9" 483 "pbZRjIeBTAvdTboGmGuqG/ljnDLJrJpoF6g8g6" 484 "fHR9eekIWis8LJ55Y1k=", 485 ttl=19283784)]) 438 486 439 440 487 class DNSServerFactoryTests(unittest.TestCase): 441 488 """ 442 489 Tests for L{server.DNSServerFactory}. … … 523 570 self.d.addCallback(self._gotResults) 524 571 self.controller = client.AXFRController('fooby.com', self.d) 525 572 526 self.soa = dns.RRHeader(name='fooby.com', type=dns.SOA, cls=dns.IN, ttl=86400, auth=False, 573 self.soa = dns.RRHeader(name='fooby.com', type=dns.SOA, cls=dns.IN, 574 ttl=86400, auth=False, 527 575 payload=dns.Record_SOA(mname='fooby.com', 528 576 rname='hooj.fooby.com', 529 577 serial=100, … … 535 583 536 584 self.records = [ 537 585 self.soa, 538 dns.RRHeader(name='fooby.com', type=dns.NS, cls=dns.IN, ttl=700, auth=False, 539 payload=dns.Record_NS(name='ns.twistedmatrix.com', ttl=700)), 586 dns.RRHeader(name='fooby.com', type=dns.NS, cls=dns.IN, ttl=700, 587 auth=False, 588 payload=dns.Record_NS(name='ns.twistedmatrix.com', 589 ttl=700)), 540 590 541 dns.RRHeader(name='fooby.com', type=dns.MX, cls=dns.IN, ttl=700, auth=False, 542 payload=dns.Record_MX(preference=10, exchange='mail.mv3d.com', ttl=700)), 591 dns.RRHeader(name='fooby.com', type=dns.MX, cls=dns.IN, ttl=700, 592 auth=False, 593 payload=dns.Record_MX(preference=10, 594 exchange='mail.mv3d.com', 595 ttl=700)), 543 596 544 dns.RRHeader(name='fooby.com', type=dns.A, cls=dns.IN, ttl=700, auth=False, 545 payload=dns.Record_A(address='64.123.27.105', ttl=700)), 597 dns.RRHeader(name='fooby.com', type=dns.A, cls=dns.IN, 598 ttl=700, auth=False, 599 payload=dns.Record_A(address='64.123.27.105', 600 ttl=700)), 546 601 self.soa 547 602 ] 548 603 549 604 def _makeMessage(self): 550 605 # hooray they all have the same message format 551 return dns.Message(id=999, answer=1, opCode=0, recDes=0, recAv=1, auth=1, rCode=0, trunc=0, maxSize=0) 606 return dns.Message(id=999, answer=1, opCode=0, recDes=0, recAv=1, 607 auth=1, rCode=0, trunc=0, maxSize=0) 552 608 553 609 def testBindAndTNamesStyle(self): 554 610 # Bind style = One big single message … … 890 946 self.assertEqual(service.domains[1].domain, 'example.edu') 891 947 892 948 893 894 949 class SecondaryAuthorityTests(unittest.TestCase): 895 950 """ 896 951 L{twisted.names.secondary.SecondaryAuthority} correctly constructs objects -
twisted/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 @since: 12.1 8 """ 9 10 from twisted.names.ser_num_arith import SNA, DateSNA 11 from twisted.names.ser_num_arith import max as sna_max 12 from twisted.trial import unittest 13 14 class SNATest(unittest.TestCase): 15 16 def setUp(self): 17 self.s1 = SNA(1) 18 self.s1a = SNA(1) 19 self.s2 = SNA(2) 20 self.sMaxVal = SNA(SNA.HLFRNG+SNA.HLFRNG-1) 21 22 def test_equality(self): 23 """ 24 Test SNA equality 25 """ 26 self.assertEqual(self.s1, self.s1a) 27 self.assertNotIdentical(self.s1, self.s1a) 28 self.assertEqual(hash(self.s1), hash(self.s1a)) 29 self.assertNotEqual(hash(self.s1), hash(self.s2)) 30 31 def test_le(self): 32 """ 33 Test SNA less than or equal 34 """ 35 self.assertTrue(self.s1 <= self.s1) 36 self.assertTrue(self.s1 <= self.s1a) 37 self.assertTrue(self.s1 <= self.s2) 38 self.assertFalse(self.s2 <= self.s1) 39 40 def test_ge(self): 41 """ 42 Test SNA greater than or equal 43 """ 44 self.assertTrue(self.s1 >= self.s1) 45 self.assertTrue(self.s1 >= self.s1a) 46 self.assertFalse(self.s1 >= self.s2) 47 self.assertTrue(self.s2 >= self.s1) 48 49 50 def test_lt(self): 51 """ 52 Test SNA less than 53 """ 54 self.assertFalse(self.s1 < self.s1) 55 self.assertFalse(self.s1 < self.s1a) 56 self.assertTrue(self.s1 < self.s2) 57 self.assertFalse(self.s2 < self.s1) 58 59 def test_gt(self): 60 """ 61 Test SNA greater than 62 """ 63 self.assertFalse(self.s1 > self.s1) 64 self.assertFalse(self.s1 > self.s1a) 65 self.assertFalse(self.s1 > self.s2) 66 self.assertTrue(self.s2 > self.s1) 67 68 def test_add(self): 69 """ 70 Test SNA addition 71 """ 72 self.assertEqual(self.s1 + self.s1, self.s2) 73 self.assertEqual(self.s1 + SNA(SNA.MAXADD), SNA(SNA.MAXADD + 1)) 74 self.assertEqual(SNA(SNA.MAXADD) + SNA(SNA.MAXADD) + SNA(2), SNA(0)) 75 76 def test_maxval(self): 77 """ 78 Test SNA maxval 79 """ 80 smaxplus1 = self.sMaxVal + self.s1 81 self.assertTrue(smaxplus1 > self.sMaxVal) 82 self.assertEqual(smaxplus1, SNA(0)) 83 84 def test_max(self): 85 """ 86 Test the SNA max function 87 """ 88 self.assertEqual(sna_max([None, self.s1]), self.s1) 89 self.assertEqual(sna_max([self.s1, None]), self.s1) 90 self.assertEqual(sna_max([self.s1, self.s1a]), self.s1) 91 self.assertEqual(sna_max([self.s2, self.s1a, self.s1, None]), self.s2) 92 self.assertEqual(sna_max([SNA(SNA.MAXADD), self.s2, self.s1a, self.s1, None]), 93 SNA(SNA.MAXADD)) 94 self.assertEqual(sna_max([self.s2, self.s1a, self.s1, None, self.sMaxVal]), 95 self.s2) 96 97 def test_dateSNA(self): 98 """ 99 Test DateSNA construction and comparison 100 """ 101 date1 = DateSNA('20120101000000') 102 date2 = DateSNA('20130101000000') 103 self.assertTrue(date1 < date2) 104 105 def test_dateAdd(self): 106 """ 107 Test DateSNA addition 108 """ 109 date3 = DateSNA('20370101000000') 110 sna1 = SNA(365*24*60*60) 111 date4 = date3 + sna1 112 self.assertEqual(date4.asInt(), date3.asInt() + sna1.asInt()) 113 114 def test_asDate(self): 115 """ 116 Test DateSNA conversion 117 """ 118 date1 = '20120101000000' 119 date1Sna = DateSNA(date1) 120 self.assertEqual(date1Sna.asDate(), date1) 121 122 def test_roundTrip(self): 123 """ 124 Test DateSNA conversion 125 """ 126 date1 = '20370101000000' 127 date1Sna = DateSNA(date1) 128 intval = date1Sna.asInt() 129 sna1a = SNA(intval) 130 131 dateSna1a = DateSNA.fromSNA(sna1a) 132 self.assertEqual(date1Sna, dateSna1a) 133 134 dateSna2 = DateSNA.fromInt(intval) 135 self.assertEqual(date1Sna, dateSna2) -
twisted/names/topfiles/5454.feature
1 Features 2 -------- 3 - The main features introduced by this change are EDNS0 and support 4 for DNSSEC. Enabling EDNS0 adds to a query an OPT record that carries 5 two pieces of information. The first is the maximum size UDP packet 6 that the network can handle (see RFC2671.) The second is the DNSSEC 7 OK (DO) bit which tells an upstream resolver that the querying resolver 8 is able to accept DNSSEC security data (See RFC3225.) Although this 9 change fully implements EDNS0, it only enables twisted.names to 10 ask for DNSSEC data and pass that data to the user. The user may 11 check the Authentic Data (AD) bit in the message header to determine 12 if the upstream resolver validates the data. (See RFC 4035, Section 13 4.9.3 regarding only using the AD bit from a trusted resolver 14 on a secure channel.) 15 - Processing DNSSEC data and validating DNS answers requires doing 16 cryptographic processing using a library such as openssl. This may 17 be part of a future feature set but is not in the current feature. 18 - The new class twisted.names.common.DnssecConfig allows configuring 19 DNSSEC and EDNS0 parameters, as well as the recursion desired DNS 20 parameter, for a resolver. DnssecConfig is an optional input argument 21 to ResolverBase and is implemented for client.Resolver and 22 secondaryAuthority.Resolver 23 - ResolverBase now has new lookup methods for lookupDNSKey, lookupDS, 24 lookupNSEC, lookupNSEC3, lookupNSEC3Param and lookupRRSIG records. 25 - twisted.names.client.Resolver now returns a 4-tuple to a query when 26 configured with dnssecOk. The 4-tuple includes a new reference 27 to the message so that the caller can obtain the AD flag (and 28 any of the other flags) in the message. 29 - twisted.names.client now has new lookup methods for the six new 30 DNSSEC record types. 31 - twisted.names.dns now supports six new DNS record types - DNSKey, 32 DS, NSEC, NSEC3, NSEC3Param and RRSIG. 33 - The new twisted.names.dns.Sigstr class encodes/decodes signatures and keys. 34 - The new twisted.names.dns.TypeBitmaps class encodes/decoes the type bitmap 35 field in an NSEC3 resource record. 36 - The new OptHeader and Record_OPT classes support the EDNS and DNSSEC 37 options. 38 - twisted.names.dns now has new classes added for the six DNSSEC record types. 39 - The dns.Message class now has new AD and CD flags for AuthenticData and Checking Disabled. 40 - twisted.names.dns now adds the OPT record to EDNS queries. 41 - twisted.names.dns.Message.startListening now listens for larger UDP 42 packets, as set by maxUdpPktSz. 43 - The new twisted.names.ser_num_arith class implements DNS Serial Number 44 Arithmetic (SNA) and Date SNA for handling numbers and dates that 45 roll through a 32-bit integer. 46 - New tests are added for all new features. 47 No newline at end of file
