diff -Naur dnspython-orig/dnspython-1.11.1/ChangeLog dnspython/dnspython-1.11.1/ChangeLog --- dnspython-orig/dnspython-1.11.1/ChangeLog 2013-09-02 14:50:25.000000000 -0400 +++ dnspython/dnspython-1.11.1/ChangeLog 2014-02-18 18:36:33.484753464 -0500 @@ -1,3 +1,9 @@ +2013-12-11 Bob Halley + + * dns/query.py: Fix problems with the IXFR state machine which caused + long diffs to fail. Thanks to James Raftery for the fix and the + repeated prodding to get it applied :) + 2013-09-02 Bob Halley * (Version 1.11.1 released) diff -Naur dnspython-orig/dnspython-1.11.1/dns/dnssec.py dnspython/dnspython-1.11.1/dns/dnssec.py --- dnspython-orig/dnspython-1.11.1/dns/dnssec.py 2013-08-09 13:03:27.000000000 -0400 +++ dnspython/dnspython-1.11.1/dns/dnssec.py 2014-02-18 18:36:33.485753475 -0500 @@ -45,6 +45,8 @@ RSASHA1NSEC3SHA1 = 7 RSASHA256 = 8 RSASHA512 = 10 +ECDSAP256SHA256 = 13 +ECDSAP384SHA384 = 14 INDIRECT = 252 PRIVATEDNS = 253 PRIVATEOID = 254 @@ -60,6 +62,8 @@ 'RSASHA256' : RSASHA256, 'RSASHA512' : RSASHA512, 'INDIRECT' : INDIRECT, + 'ECDSAP256SHA256' : ECDSAP256SHA256, + 'ECDSAP384SHA384' : ECDSAP384SHA384, 'PRIVATEDNS' : PRIVATEDNS, 'PRIVATEOID' : PRIVATEOID, } @@ -153,6 +157,9 @@ def _is_dsa(algorithm): return algorithm in (DSA, DSANSEC3SHA1) +def _is_ecdsa(algorithm): + return _have_ecdsa and (algorithm in (ECDSAP256SHA256, ECDSAP384SHA384)) + def _is_md5(algorithm): return algorithm == RSAMD5 @@ -161,7 +168,10 @@ DSANSEC3SHA1, RSASHA1NSEC3SHA1) def _is_sha256(algorithm): - return algorithm == RSASHA256 + return algorithm in (RSASHA256, ECDSAP256SHA256) + +def _is_sha384(algorithm): + return algorithm == ECDSAP384SHA384 def _is_sha512(algorithm): return algorithm == RSASHA512 @@ -173,6 +183,8 @@ return dns.hash.get('SHA1')() if _is_sha256(algorithm): return dns.hash.get('SHA256')() + if _is_sha384(algorithm): + return dns.hash.get('SHA384')() if _is_sha512(algorithm): return dns.hash.get('SHA512')() raise ValidationFailure, 'unknown hash for algorithm %u' % algorithm @@ -274,6 +286,30 @@ (dsa_r, dsa_s) = struct.unpack('!20s20s', rrsig.signature[1:]) sig = (Crypto.Util.number.bytes_to_long(dsa_r), Crypto.Util.number.bytes_to_long(dsa_s)) + elif _is_ecdsa(rrsig.algorithm): + if rrsig.algorithm == ECDSAP256SHA256: + curve = ecdsa.curves.NIST256p + key_len = 32 + digest_len = 32 + elif rrsig.algorithm == ECDSAP384SHA384: + curve = ecdsa.curves.NIST384p + key_len = 48 + digest_len = 48 + else: + # shouldn't happen + raise ValidationFailure, 'unknown ECDSA curve' + keyptr = candidate_key.key + x = Crypto.Util.number.bytes_to_long(keyptr[0:key_len]) + y = Crypto.Util.number.bytes_to_long(keyptr[key_len:key_len * 2]) + assert ecdsa.ecdsa.point_is_valid(curve.generator, x, y) + point = ecdsa.ellipticcurve.Point(curve.curve, x, y, curve.order) + verifying_key = ecdsa.keys.VerifyingKey.from_public_point(point, + curve) + pubkey = ECKeyWrapper(verifying_key, key_len) + r = rrsig.signature[:key_len] + s = rrsig.signature[key_len:] + sig = ecdsa.ecdsa.Signature(Crypto.Util.number.bytes_to_long(r), + Crypto.Util.number.bytes_to_long(s)) else: raise ValidationFailure, 'unknown algorithm %u' % rrsig.algorithm @@ -302,7 +338,7 @@ digest = _make_algorithm_id(rrsig.algorithm) + digest padlen = keylen // 8 - len(digest) - 3 digest = chr(0) + chr(1) + chr(0xFF) * padlen + chr(0) + digest - elif _is_dsa(rrsig.algorithm): + elif _is_dsa(rrsig.algorithm) or _is_ecdsa(rrsig.algorithm): pass else: # Raise here for code clarity; this won't actually ever happen @@ -372,3 +408,21 @@ except ImportError: validate = _need_pycrypto validate_rrsig = _need_pycrypto + +try: + import ecdsa + import ecdsa.ecdsa + import ecdsa.ellipticcurve + import ecdsa.keys + _have_ecdsa = True + + class ECKeyWrapper(object): + def __init__(self, key, key_len): + self.key = key + self.key_len = key_len + def verify(self, digest, sig): + diglong = Crypto.Util.number.bytes_to_long(digest) + return self.key.pubkey.verifies(diglong, sig) + +except ImportError: + _have_ecdsa = False diff -Naur dnspython-orig/dnspython-1.11.1/dns/query.py dnspython/dnspython-1.11.1/dns/query.py --- dnspython-orig/dnspython-1.11.1/dns/query.py 2013-08-26 12:04:21.000000000 -0400 +++ dnspython/dnspython-1.11.1/dns/query.py 2014-02-18 18:36:33.486753487 -0500 @@ -411,6 +411,8 @@ tcpmsg = struct.pack("!H", l) + wire _net_write(s, tcpmsg, expiration) done = False + delete_mode = True + expecting_SOA = False soa_rrset = None soa_count = 0 if relativize: @@ -439,18 +441,16 @@ tsig_ctx = r.tsig_ctx first = False answer_index = 0 - delete_mode = False - expecting_SOA = False if soa_rrset is None: if not r.answer or r.answer[0].name != oname: - raise dns.exception.FormError + raise dns.exception.FormError("No answer or RRset not for qname") rrset = r.answer[0] if rrset.rdtype != dns.rdatatype.SOA: raise dns.exception.FormError("first RRset is not an SOA") answer_index = 1 soa_rrset = rrset.copy() if rdtype == dns.rdatatype.IXFR: - if soa_rrset[0].serial == serial: + if soa_rrset[0].serial <= serial: # # We're already up-to-date. # @@ -471,7 +471,14 @@ expecting_SOA = False elif rdtype == dns.rdatatype.IXFR: delete_mode = not delete_mode - if rrset == soa_rrset and not delete_mode: + # + # If this SOA RRset is equal to the first we saw then we're + # finished. If this is an IXFR we also check that we're seeing + # the record in the expected part of the response. + # + if rrset == soa_rrset and \ + (rdtype == dns.rdatatype.AXFR or \ + (rdtype == dns.rdatatype.IXFR and delete_mode)): done = True elif expecting_SOA: # diff -Naur dnspython-orig/dnspython-1.11.1/dns/rdtypes/ANY/LOC.py dnspython/dnspython-1.11.1/dns/rdtypes/ANY/LOC.py --- dnspython-orig/dnspython-1.11.1/dns/rdtypes/ANY/LOC.py 2011-07-09 10:05:21.000000000 -0400 +++ dnspython/dnspython-1.11.1/dns/rdtypes/ANY/LOC.py 2014-02-18 18:36:33.487753499 -0500 @@ -22,6 +22,11 @@ _pows = (1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 100000000L, 1000000000L, 10000000000L) +# default values are in centimeters +_default_size = 100.0 +_default_hprec = 1000000.0 +_default_vprec = 1000.0 + def _exponent_of(what, desc): exp = None for i in xrange(len(_pows)): @@ -98,13 +103,14 @@ 'horizontal_precision', 'vertical_precision'] def __init__(self, rdclass, rdtype, latitude, longitude, altitude, - size=1.0, hprec=10000.0, vprec=10.0): + size=_default_size, hprec=_default_hprec, vprec=_default_vprec): """Initialize a LOC record instance. The parameters I{latitude} and I{longitude} may be either a 4-tuple of integers specifying (degrees, minutes, seconds, milliseconds), or they may be floating point values specifying the number of - degrees. The other parameters are floats.""" + degrees. The other parameters are floats. Size, horizontal precision, + and vertical precision are specified in centimeters.""" super(LOC, self).__init__(rdclass, rdtype) if isinstance(latitude, int) or isinstance(latitude, long): @@ -141,8 +147,10 @@ self.longitude[3], long_hemisphere, self.altitude / 100.0 ) - if self.size != 1.0 or self.horizontal_precision != 10000.0 or \ - self.vertical_precision != 10.0: + # do not print default values + if self.size != _default_size or \ + self.horizontal_precision != _default_hprec or \ + self.vertical_precision != _default_vprec: text += " %0.2fm %0.2fm %0.2fm" % ( self.size / 100.0, self.horizontal_precision / 100.0, self.vertical_precision / 100.0 @@ -152,9 +160,9 @@ def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): latitude = [0, 0, 0, 0] longitude = [0, 0, 0, 0] - size = 1.0 - hprec = 10000.0 - vprec = 10.0 + size = _default_size + hprec = _default_hprec + vprec = _default_vprec latitude[0] = tok.get_int() t = tok.get_string() @@ -240,8 +248,8 @@ value = token.value if value[-1] == 'm': value = value[0 : -1] - vprec = float(value) * 100.0 # m -> cm - tok.get_eol() + vprec = float(value) * 100.0 # m -> cm + tok.get_eol() return cls(rdclass, rdtype, latitude, longitude, altitude, size, hprec, vprec) diff -Naur dnspython-orig/dnspython-1.11.1/tests/dnssec.py dnspython/dnspython-1.11.1/tests/dnssec.py --- dnspython-orig/dnspython-1.11.1/tests/dnssec.py 2013-03-31 06:33:53.000000000 -0400 +++ dnspython/dnspython-1.11.1/tests/dnssec.py 2014-02-18 18:36:33.487753499 -0500 @@ -97,6 +97,40 @@ example_ds_sha256 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, '18673 3 2 eb8344cbbf07c9d3d3d6c81d10c76653e28d8611a65e639ef8f716e4e4e5d913') +when3 = 1379801800 + +abs_ecdsa256_keys = { abs_example : + dns.rrset.from_text('example.', 86400, 'IN', 'DNSKEY', + "256 3 13 +3ss1sCpdARVA61DJigEsL/8quo2a8MszKtn2gkkfxgzFs8S2UHtpb4N fY+XFmNW+JK6MsCkI3jHYN8eEQUgMw==", + "257 3 13 eJCEVH7AS3wnoaQpaNlAXH0W8wxymtT9P6P3qjN2ZCV641ED8pF7wZ5V yWfOpgTs6oaZevbJgehl/GaRPUgVyQ==") + } + +abs_ecdsa256_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 4 10800 3600 604800 86400') + +abs_other_ecdsa256_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') + +abs_ecdsa256_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', + "SOA 13 1 86400 20130921221753 20130921221638 7460 example. Sm09SOGz1ULB5D/duwdE2Zpn8bWbVBM77H6N1wPkc42LevvVO+kZEjpq 2nq4GOMJcih52667GIAbMrwmU5P2MQ==") + +when4 = 1379804850 + +abs_ecdsa384_keys = { abs_example : + dns.rrset.from_text('example.', 86400, 'IN', 'DNSKEY', + "256 3 14 1bG8qWviKNXQX3BIuG6/T5jrP1FISiLW/8qGF6BsM9DQtWYhhZUA3Owr OAEiyHAhQwjkN2kTvWiAYoPN80Ii+5ff9/atzY4F9W50P4l75Dj9PYrL HN/hLUgWMNVc9pvA", + "257 3 14 mSub2n0KRt6u2FaD5XJ3oQu0R4XvB/9vUJcyW6+oo0y+KzfQeTdkf1ro ZMVKoyWXW9zUKBYGJpMUIdbAxzrYi7f5HyZ3yDpBFz1hw9+o3CX+gtgb +RyhHfJDwwFXBid9") + } + +abs_ecdsa384_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86400') + +abs_other_ecdsa384_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') + +abs_ecdsa384_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', + "SOA 14 1 86400 20130929021229 20130921230729 63571 example. CrnCu34EeeRz0fEhL9PLlwjpBKGYW8QjBjFQTwd+ViVLRAS8tNkcDwQE NhSV89NEjj7ze1a/JcCfcJ+/mZgnvH4NHLNg3Tf6KuLZsgs2I4kKQXEk 37oIHravPEOlGYNI") + class DNSSECValidatorTestCase(unittest.TestCase): def testAbsoluteRSAGood(self): @@ -143,6 +177,35 @@ ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA256') self.failUnless(ds == example_ds_sha256) + @unittest.skipIf(not dns.dnssec._have_ecdsa, + "python ECDSA can not be imported") + def testAbsoluteECDSA256Good(self): + dns.dnssec.validate(abs_ecdsa256_soa, abs_ecdsa256_soa_rrsig, + abs_ecdsa256_keys, None, when3) + + @unittest.skipIf(not dns.dnssec._have_ecdsa, + "python ECDSA can not be imported") + def testAbsoluteECDSA256Bad(self): + def bad(): + dns.dnssec.validate(abs_other_ecdsa256_soa, abs_ecdsa256_soa_rrsig, + abs_ecdsa256_keys, None, when3) + self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) + + @unittest.skipIf(not dns.dnssec._have_ecdsa, + "python ECDSA can not be imported") + def testAbsoluteECDSA384Good(self): + dns.dnssec.validate(abs_ecdsa384_soa, abs_ecdsa384_soa_rrsig, + abs_ecdsa384_keys, None, when4) + + @unittest.skipIf(not dns.dnssec._have_ecdsa, + "python ECDSA can not be imported") + def testAbsoluteECDSA384Bad(self): + def bad(): + dns.dnssec.validate(abs_other_ecdsa384_soa, abs_ecdsa384_soa_rrsig, + abs_ecdsa384_keys, None, when4) + self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) + + if __name__ == '__main__': import_ok = False try: diff -Naur dnspython-orig/dnspython-1.11.1/tests/rdtypeanyloc.py dnspython/dnspython-1.11.1/tests/rdtypeanyloc.py --- dnspython-orig/dnspython-1.11.1/tests/rdtypeanyloc.py 1969-12-31 19:00:00.000000000 -0500 +++ dnspython/dnspython-1.11.1/tests/rdtypeanyloc.py 2014-02-18 18:36:33.488753510 -0500 @@ -0,0 +1,68 @@ +# Copyright (C) 2014 Red Hat, Inc. +# Author: Petr Spacek +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.rrset +import dns.rdtypes.ANY.LOC + +class RdtypeAnyLocTestCase(unittest.TestCase): + + def testEqual1(self): + '''Test default values for size, horizontal and vertical precision.''' + r1 = dns.rrset.from_text('foo', 300, 'IN', 'LOC', + '49 11 42.400 N 16 36 29.600 E 227.64m') + r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', + '49 11 42.400 N 16 36 29.600 E 227.64m ' + '1.00m 10000.00m 10.00m') + self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) + + def testEqual2(self): + '''Test default values for size, horizontal and vertical precision.''' + r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), + (16, 36, 29, 600), 22764.0) # centimeters + r2 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), + (16, 36, 29, 600), 22764.0, # centimeters + 100.0, 1000000.00, 1000.0) # centimeters + self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) + + def testEqual3(self): + '''Test size, horizontal and vertical precision parsers: 100 cm == 1 m. + + Parsers in from_text() and __init__() have to produce equal results.''' + r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), + (16, 36, 29, 600), 22764.0, + 200.0, 1000.00, 200.0) # centimeters + r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', + '49 11 42.400 N 16 36 29.600 E 227.64m ' + '2.00m 10.00m 2.00m')[0] + self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) + + def testEqual4(self): + '''Test size, horizontal and vertical precision parsers without unit. + + Parsers in from_text() and __init__() have produce equal result + for values with and without trailing "m".''' + r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), + (16, 36, 29, 600), 22764.0, + 200.0, 1000.00, 200.0) # centimeters + r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', + '49 11 42.400 N 16 36 29.600 E 227.64 ' + '2 10 2')[0] # meters without explicit unit + self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) + +if __name__ == '__main__': + unittest.main() diff -Naur dnspython-orig/dnspython3-1.11.1/ChangeLog dnspython/dnspython3-1.11.1/ChangeLog --- dnspython-orig/dnspython3-1.11.1/ChangeLog 2013-09-02 14:59:21.000000000 -0400 +++ dnspython/dnspython3-1.11.1/ChangeLog 2014-02-18 18:36:33.489753522 -0500 @@ -1,3 +1,9 @@ +2013-12-11 Bob Halley + + * dns/query.py: Fix problems with the IXFR state machine which caused + long diffs to fail. Thanks to James Raftery for the fix and the + repeated prodding to get it applied :) + 2013-09-02 Bob Halley * (Version 1.11.1 released) diff -Naur dnspython-orig/dnspython3-1.11.1/dns/dnssec.py dnspython/dnspython3-1.11.1/dns/dnssec.py --- dnspython-orig/dnspython3-1.11.1/dns/dnssec.py 2013-08-09 13:04:11.000000000 -0400 +++ dnspython/dnspython3-1.11.1/dns/dnssec.py 2014-02-18 18:37:09.537175404 -0500 @@ -45,6 +45,8 @@ RSASHA1NSEC3SHA1 = 7 RSASHA256 = 8 RSASHA512 = 10 +ECDSAP256SHA256 = 13 +ECDSAP384SHA384 = 14 INDIRECT = 252 PRIVATEDNS = 253 PRIVATEOID = 254 @@ -60,6 +62,8 @@ 'RSASHA256' : RSASHA256, 'RSASHA512' : RSASHA512, 'INDIRECT' : INDIRECT, + 'ECDSAP256SHA256' : ECDSAP256SHA256, + 'ECDSAP384SHA384' : ECDSAP384SHA384, 'PRIVATEDNS' : PRIVATEDNS, 'PRIVATEOID' : PRIVATEOID, } @@ -153,6 +157,9 @@ def _is_dsa(algorithm): return algorithm in (DSA, DSANSEC3SHA1) +def _is_ecdsa(algorithm): + return _have_ecdsa and (algorithm in (ECDSAP256SHA256, ECDSAP384SHA384)) + def _is_md5(algorithm): return algorithm == RSAMD5 @@ -161,7 +168,10 @@ DSANSEC3SHA1, RSASHA1NSEC3SHA1) def _is_sha256(algorithm): - return algorithm == RSASHA256 + return algorithm in (RSASHA256, ECDSAP256SHA256) + +def _is_sha384(algorithm): + return algorithm == ECDSAP384SHA384 def _is_sha512(algorithm): return algorithm == RSASHA512 @@ -173,6 +183,8 @@ return dns.hash.get('SHA1')() if _is_sha256(algorithm): return dns.hash.get('SHA256')() + if _is_sha384(algorithm): + return dns.hash.get('SHA384')() if _is_sha512(algorithm): return dns.hash.get('SHA512')() raise ValidationFailure('unknown hash for algorithm %u' % algorithm) @@ -274,6 +286,30 @@ (dsa_r, dsa_s) = struct.unpack('!20s20s', rrsig.signature[1:]) sig = (Crypto.Util.number.bytes_to_long(dsa_r), Crypto.Util.number.bytes_to_long(dsa_s)) + elif _is_ecdsa(rrsig.algorithm): + if rrsig.algorithm == ECDSAP256SHA256: + curve = ecdsa.curves.NIST256p + key_len = 32 + digest_len = 32 + elif rrsig.algorithm == ECDSAP384SHA384: + curve = ecdsa.curves.NIST384p + key_len = 48 + digest_len = 48 + else: + # shouldn't happen + raise ValidationFailure('unknown ECDSA curve') + keyptr = candidate_key.key + x = Crypto.Util.number.bytes_to_long(keyptr[0:key_len]) + y = Crypto.Util.number.bytes_to_long(keyptr[key_len:key_len * 2]) + assert ecdsa.ecdsa.point_is_valid(curve.generator, x, y) + point = ecdsa.ellipticcurve.Point(curve.curve, x, y, curve.order) + verifying_key = ecdsa.keys.VerifyingKey.from_public_point(point, + curve) + pubkey = ECKeyWrapper(verifying_key, key_len) + r = rrsig.signature[:key_len] + s = rrsig.signature[key_len:] + sig = ecdsa.ecdsa.Signature(Crypto.Util.number.bytes_to_long(r), + Crypto.Util.number.bytes_to_long(s)) else: raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) @@ -303,7 +339,7 @@ padlen = keylen // 8 - len(digest) - 3 digest = bytes([0]) + bytes([1]) + bytes([0xFF]) * padlen + \ bytes([0]) + digest - elif _is_dsa(rrsig.algorithm): + elif _is_dsa(rrsig.algorithm) or _is_ecdsa(rrsig.algorithm): pass else: # Raise here for code clarity; this won't actually ever happen @@ -373,3 +409,21 @@ except ImportError: validate = _need_pycrypto validate_rrsig = _need_pycrypto + +try: + import ecdsa + import ecdsa.ecdsa + import ecdsa.ellipticcurve + import ecdsa.keys + _have_ecdsa = True + + class ECKeyWrapper(object): + def __init__(self, key, key_len): + self.key = key + self.key_len = key_len + def verify(self, digest, sig): + diglong = Crypto.Util.number.bytes_to_long(digest) + return self.key.pubkey.verifies(diglong, sig) + +except ImportError: + _have_ecdsa = False diff -Naur dnspython-orig/dnspython3-1.11.1/dns/dnssec.py.orig dnspython/dnspython3-1.11.1/dns/dnssec.py.orig --- dnspython-orig/dnspython3-1.11.1/dns/dnssec.py.orig 1969-12-31 19:00:00.000000000 -0500 +++ dnspython/dnspython3-1.11.1/dns/dnssec.py.orig 2014-02-18 18:36:33.490753534 -0500 @@ -0,0 +1,375 @@ +# Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +"""Common DNSSEC-related functions and constants.""" + +import io +import struct +import time + +import dns.exception +import dns.hash +import dns.name +import dns.node +import dns.rdataset +import dns.rdata +import dns.rdatatype +import dns.rdataclass + +class UnsupportedAlgorithm(dns.exception.DNSException): + """Raised if an algorithm is not supported.""" + pass + +class ValidationFailure(dns.exception.DNSException): + """The DNSSEC signature is invalid.""" + pass + +RSAMD5 = 1 +DH = 2 +DSA = 3 +ECC = 4 +RSASHA1 = 5 +DSANSEC3SHA1 = 6 +RSASHA1NSEC3SHA1 = 7 +RSASHA256 = 8 +RSASHA512 = 10 +INDIRECT = 252 +PRIVATEDNS = 253 +PRIVATEOID = 254 + +_algorithm_by_text = { + 'RSAMD5' : RSAMD5, + 'DH' : DH, + 'DSA' : DSA, + 'ECC' : ECC, + 'RSASHA1' : RSASHA1, + 'DSANSEC3SHA1' : DSANSEC3SHA1, + 'RSASHA1NSEC3SHA1' : RSASHA1NSEC3SHA1, + 'RSASHA256' : RSASHA256, + 'RSASHA512' : RSASHA512, + 'INDIRECT' : INDIRECT, + 'PRIVATEDNS' : PRIVATEDNS, + 'PRIVATEOID' : PRIVATEOID, + } + +# We construct the inverse mapping programmatically to ensure that we +# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that +# would cause the mapping not to be true inverse. + +_algorithm_by_value = dict([(y, x) for x, y in _algorithm_by_text.items()]) + +def algorithm_from_text(text): + """Convert text into a DNSSEC algorithm value + @rtype: int""" + + value = _algorithm_by_text.get(text.upper()) + if value is None: + value = int(text) + return value + +def algorithm_to_text(value): + """Convert a DNSSEC algorithm value to text + @rtype: string""" + + text = _algorithm_by_value.get(value) + if text is None: + text = str(value) + return text + +def _to_rdata(record, origin): + s = io.BytesIO() + record.to_wire(s, origin=origin) + return s.getvalue() + +def key_id(key, origin=None): + rdata = _to_rdata(key, origin) + if key.algorithm == RSAMD5: + return (rdata[-3] << 8) + rdata[-2] + else: + total = 0 + for i in range(len(rdata) // 2): + total += (rdata[2 * i] << 8) + rdata[2 * i + 1] + if len(rdata) % 2 != 0: + total += rdata[len(rdata) - 1] << 8 + total += ((total >> 16) & 0xffff); + return total & 0xffff + +def make_ds(name, key, algorithm, origin=None): + if algorithm.upper() == 'SHA1': + dsalg = 1 + hash = dns.hash.get('SHA1')() + elif algorithm.upper() == 'SHA256': + dsalg = 2 + hash = dns.hash.get('SHA256')() + else: + raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm) + + if isinstance(name, str): + name = dns.name.from_text(name, origin) + hash.update(name.canonicalize().to_wire()) + hash.update(_to_rdata(key, origin)) + digest = hash.digest() + + dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, dsalg) + digest + return dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0, + len(dsrdata)) + +def _find_candidate_keys(keys, rrsig): + candidate_keys=[] + value = keys.get(rrsig.signer) + if value is None: + return None + if isinstance(value, dns.node.Node): + try: + rdataset = value.find_rdataset(dns.rdataclass.IN, + dns.rdatatype.DNSKEY) + except KeyError: + return None + else: + rdataset = value + for rdata in rdataset: + if rdata.algorithm == rrsig.algorithm and \ + key_id(rdata) == rrsig.key_tag: + candidate_keys.append(rdata) + return candidate_keys + +def _is_rsa(algorithm): + return algorithm in (RSAMD5, RSASHA1, + RSASHA1NSEC3SHA1, RSASHA256, + RSASHA512) + +def _is_dsa(algorithm): + return algorithm in (DSA, DSANSEC3SHA1) + +def _is_md5(algorithm): + return algorithm == RSAMD5 + +def _is_sha1(algorithm): + return algorithm in (DSA, RSASHA1, + DSANSEC3SHA1, RSASHA1NSEC3SHA1) + +def _is_sha256(algorithm): + return algorithm == RSASHA256 + +def _is_sha512(algorithm): + return algorithm == RSASHA512 + +def _make_hash(algorithm): + if _is_md5(algorithm): + return dns.hash.get('MD5')() + if _is_sha1(algorithm): + return dns.hash.get('SHA1')() + if _is_sha256(algorithm): + return dns.hash.get('SHA256')() + if _is_sha512(algorithm): + return dns.hash.get('SHA512')() + raise ValidationFailure('unknown hash for algorithm %u' % algorithm) + +def _make_algorithm_id(algorithm): + if _is_md5(algorithm): + oid = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05] + elif _is_sha1(algorithm): + oid = [0x2b, 0x0e, 0x03, 0x02, 0x1a] + elif _is_sha256(algorithm): + oid = [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01] + elif _is_sha512(algorithm): + oid = [0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03] + else: + raise ValidationFailure('unknown algorithm %u' % algorithm) + olen = len(oid) + dlen = _make_hash(algorithm).digest_size + idbytes = [0x30] + [8 + olen + dlen] + \ + [0x30, olen + 4] + [0x06, olen] + oid + \ + [0x05, 0x00] + [0x04, dlen] + return bytes(idbytes) + +def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + """Validate an RRset against a single signature rdata + + The owner name of the rrsig is assumed to be the same as the owner name + of the rrset. + + @param rrset: The RRset to validate + @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset) + tuple + @param rrsig: The signature rdata + @type rrsig: dns.rrset.Rdata + @param keys: The key dictionary. + @type keys: a dictionary keyed by dns.name.Name with node or rdataset values + @param origin: The origin to use for relative names + @type origin: dns.name.Name or None + @param now: The time to use when validating the signatures. The default + is the current time. + @type now: int + """ + + if isinstance(origin, str): + origin = dns.name.from_text(origin, dns.name.root) + + for candidate_key in _find_candidate_keys(keys, rrsig): + if not candidate_key: + raise ValidationFailure('unknown key') + + # For convenience, allow the rrset to be specified as a (name, rdataset) + # tuple as well as a proper rrset + if isinstance(rrset, tuple): + rrname = rrset[0] + rdataset = rrset[1] + else: + rrname = rrset.name + rdataset = rrset + + if now is None: + now = time.time() + if rrsig.expiration < now: + raise ValidationFailure('expired') + if rrsig.inception > now: + raise ValidationFailure('not yet valid') + + hash = _make_hash(rrsig.algorithm) + + if _is_rsa(rrsig.algorithm): + keyptr = candidate_key.key + (count,) = struct.unpack('!B', keyptr[0:1]) + keyptr = keyptr[1:] + if count == 0: + (count,) = struct.unpack('!H', keyptr[0:2]) + keyptr = keyptr[2:] + rsa_e = keyptr[0:count] + rsa_n = keyptr[count:] + keylen = len(rsa_n) * 8 + pubkey = Crypto.PublicKey.RSA.construct( + (Crypto.Util.number.bytes_to_long(rsa_n), + Crypto.Util.number.bytes_to_long(rsa_e))) + sig = (Crypto.Util.number.bytes_to_long(rrsig.signature),) + elif _is_dsa(rrsig.algorithm): + keyptr = candidate_key.key + (t,) = struct.unpack('!B', keyptr[0:1]) + keyptr = keyptr[1:] + octets = 64 + t * 8 + dsa_q = keyptr[0:20] + keyptr = keyptr[20:] + dsa_p = keyptr[0:octets] + keyptr = keyptr[octets:] + dsa_g = keyptr[0:octets] + keyptr = keyptr[octets:] + dsa_y = keyptr[0:octets] + pubkey = Crypto.PublicKey.DSA.construct( + (Crypto.Util.number.bytes_to_long(dsa_y), + Crypto.Util.number.bytes_to_long(dsa_g), + Crypto.Util.number.bytes_to_long(dsa_p), + Crypto.Util.number.bytes_to_long(dsa_q))) + (dsa_r, dsa_s) = struct.unpack('!20s20s', rrsig.signature[1:]) + sig = (Crypto.Util.number.bytes_to_long(dsa_r), + Crypto.Util.number.bytes_to_long(dsa_s)) + else: + raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) + + hash.update(_to_rdata(rrsig, origin)[:18]) + hash.update(rrsig.signer.to_digestable(origin)) + + if rrsig.labels < len(rrname) - 1: + suffix = rrname.split(rrsig.labels + 1)[1] + rrname = dns.name.from_text('*', suffix) + rrnamebuf = rrname.to_digestable(origin) + rrfixed = struct.pack('!HHI', rdataset.rdtype, rdataset.rdclass, + rrsig.original_ttl) + rrlist = sorted(rdataset); + for rr in rrlist: + hash.update(rrnamebuf) + hash.update(rrfixed) + rrdata = rr.to_digestable(origin) + rrlen = struct.pack('!H', len(rrdata)) + hash.update(rrlen) + hash.update(rrdata) + + digest = hash.digest() + + if _is_rsa(rrsig.algorithm): + # PKCS1 algorithm identifier goop + digest = _make_algorithm_id(rrsig.algorithm) + digest + padlen = keylen // 8 - len(digest) - 3 + digest = bytes([0]) + bytes([1]) + bytes([0xFF]) * padlen + \ + bytes([0]) + digest + elif _is_dsa(rrsig.algorithm): + pass + else: + # Raise here for code clarity; this won't actually ever happen + # since if the algorithm is really unknown we'd already have + # raised an exception above + raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) + + if pubkey.verify(digest, sig): + return + raise ValidationFailure('verify failure') + +def _validate(rrset, rrsigset, keys, origin=None, now=None): + """Validate an RRset + + @param rrset: The RRset to validate + @type rrset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset) + tuple + @param rrsigset: The signature RRset + @type rrsigset: dns.rrset.RRset or (dns.name.Name, dns.rdataset.Rdataset) + tuple + @param keys: The key dictionary. + @type keys: a dictionary keyed by dns.name.Name with node or rdataset values + @param origin: The origin to use for relative names + @type origin: dns.name.Name or None + @param now: The time to use when validating the signatures. The default + is the current time. + @type now: int + """ + + if isinstance(origin, str): + origin = dns.name.from_text(origin, dns.name.root) + + if isinstance(rrset, tuple): + rrname = rrset[0] + else: + rrname = rrset.name + + if isinstance(rrsigset, tuple): + rrsigname = rrsigset[0] + rrsigrdataset = rrsigset[1] + else: + rrsigname = rrsigset.name + rrsigrdataset = rrsigset + + rrname = rrname.choose_relativity(origin) + rrsigname = rrname.choose_relativity(origin) + if rrname != rrsigname: + raise ValidationFailure("owner names do not match") + + for rrsig in rrsigrdataset: + try: + _validate_rrsig(rrset, rrsig, keys, origin, now) + return + except ValidationFailure: + pass + raise ValidationFailure("no RRSIGs validated") + +def _need_pycrypto(*args, **kwargs): + raise NotImplementedError("DNSSEC validation requires pycrypto") + +try: + import Crypto.PublicKey.RSA + import Crypto.PublicKey.DSA + import Crypto.Util.number + validate = _validate + validate_rrsig = _validate_rrsig +except ImportError: + validate = _need_pycrypto + validate_rrsig = _need_pycrypto diff -Naur dnspython-orig/dnspython3-1.11.1/dns/query.py dnspython/dnspython3-1.11.1/dns/query.py --- dnspython-orig/dnspython3-1.11.1/dns/query.py 2012-05-31 04:19:04.000000000 -0400 +++ dnspython/dnspython3-1.11.1/dns/query.py 2014-02-18 18:36:33.491753545 -0500 @@ -411,6 +411,8 @@ tcpmsg = struct.pack("!H", l) + wire _net_write(s, tcpmsg, expiration) done = False + delete_mode = True + expecting_SOA = False soa_rrset = None soa_count = 0 if relativize: @@ -439,18 +441,16 @@ tsig_ctx = r.tsig_ctx first = False answer_index = 0 - delete_mode = False - expecting_SOA = False if soa_rrset is None: if not r.answer or r.answer[0].name != oname: - raise dns.exception.FormError + raise dns.exception.FormError("No answer or RRset not for qname") rrset = r.answer[0] if rrset.rdtype != dns.rdatatype.SOA: raise dns.exception.FormError("first RRset is not an SOA") answer_index = 1 soa_rrset = rrset.copy() if rdtype == dns.rdatatype.IXFR: - if soa_rrset[0].serial == serial: + if soa_rrset[0].serial <= serial: # # We're already up-to-date. # @@ -471,7 +471,14 @@ expecting_SOA = False elif rdtype == dns.rdatatype.IXFR: delete_mode = not delete_mode - if rrset == soa_rrset and not delete_mode: + # + # If this SOA RRset is equal to the first we saw then we're + # finished. If this is an IXFR we also check that we're seeing + # the record in the expected part of the response. + # + if rrset == soa_rrset and \ + (rdtype == dns.rdatatype.AXFR or \ + (rdtype == dns.rdatatype.IXFR and delete_mode)): done = True elif expecting_SOA: # diff -Naur dnspython-orig/dnspython3-1.11.1/dns/rdtypes/ANY/LOC.py dnspython/dnspython3-1.11.1/dns/rdtypes/ANY/LOC.py --- dnspython-orig/dnspython3-1.11.1/dns/rdtypes/ANY/LOC.py 2011-07-09 10:08:27.000000000 -0400 +++ dnspython/dnspython3-1.11.1/dns/rdtypes/ANY/LOC.py 2014-02-18 18:36:33.491753545 -0500 @@ -23,6 +23,11 @@ _pows = (1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000) +# default values are in centimeters +_default_size = 100.0 +_default_hprec = 1000000.0 +_default_vprec = 1000.0 + def _exponent_of(what, desc): exp = None for i in range(len(_pows)): @@ -98,13 +103,14 @@ 'horizontal_precision', 'vertical_precision'] def __init__(self, rdclass, rdtype, latitude, longitude, altitude, - size=1.0, hprec=10000.0, vprec=10.0): + size=_default_size, hprec=_default_hprec, vprec=_default_vprec): """Initialize a LOC record instance. The parameters I{latitude} and I{longitude} may be either a 4-tuple of integers specifying (degrees, minutes, seconds, milliseconds), or they may be floating point values specifying the number of - degrees. The other parameters are floats.""" + degrees. The other parameters are floats. Size, horizontal precision, + and vertical precision are specified in centimeters.""" super(LOC, self).__init__(rdclass, rdtype) if isinstance(latitude, int): @@ -141,8 +147,10 @@ self.longitude[3], long_hemisphere, self.altitude / 100.0 ) - if self.size != 1.0 or self.horizontal_precision != 10000.0 or \ - self.vertical_precision != 10.0: + # do not print default values + if self.size != _default_size or \ + self.horizontal_precision != _default_hprec or \ + self.vertical_precision != _default_vprec: text += " %0.2fm %0.2fm %0.2fm" % ( self.size / 100.0, self.horizontal_precision / 100.0, self.vertical_precision / 100.0 @@ -152,9 +160,9 @@ def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): latitude = [0, 0, 0, 0] longitude = [0, 0, 0, 0] - size = 1.0 - hprec = 10000.0 - vprec = 10.0 + size = _default_size + hprec = _default_hprec + vprec = _default_vprec latitude[0] = tok.get_int() t = tok.get_string() @@ -240,8 +248,8 @@ value = token.value if value[-1] == 'm': value = value[0 : -1] - vprec = float(value) * 100.0 # m -> cm - tok.get_eol() + vprec = float(value) * 100.0 # m -> cm + tok.get_eol() return cls(rdclass, rdtype, latitude, longitude, altitude, size, hprec, vprec) diff -Naur dnspython-orig/dnspython3-1.11.1/dns/rdtypes/ANY/LOC.py.orig dnspython/dnspython3-1.11.1/dns/rdtypes/ANY/LOC.py.orig --- dnspython-orig/dnspython3-1.11.1/dns/rdtypes/ANY/LOC.py.orig 1969-12-31 19:00:00.000000000 -0500 +++ dnspython/dnspython3-1.11.1/dns/rdtypes/ANY/LOC.py.orig 2014-02-18 18:36:33.491753545 -0500 @@ -0,0 +1,334 @@ +# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import io +import struct + +import dns.exception +import dns.rdata +import dns.util + +_pows = (1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, + 100000000, 1000000000, 10000000000) + +def _exponent_of(what, desc): + exp = None + for i in range(len(_pows)): + if what // _pows[i] == 0: + exp = i - 1 + break + if exp is None or exp < 0: + raise dns.exception.SyntaxError("%s value out of bounds" % desc) + return exp + +def _float_to_tuple(what): + if what < 0: + sign = -1 + what *= -1 + else: + sign = 1 + what = int(round(what * 3600000)) + degrees = what // 3600000 + what -= degrees * 3600000 + minutes = what // 60000 + what -= minutes * 60000 + seconds = what // 1000 + what -= seconds * 1000 + return (degrees * sign, minutes, seconds, what) + +def _tuple_to_float(what): + if what[0] < 0: + sign = -1 + value = float(what[0]) * -1 + else: + sign = 1 + value = float(what[0]) + value += float(what[1]) / 60.0 + value += float(what[2]) / 3600.0 + value += float(what[3]) / 3600000.0 + return sign * value + +def _encode_size(what, desc): + what = int(what); + exponent = _exponent_of(what, desc) & 0xF + base = what // pow(10, exponent) & 0xF + return base * 16 + exponent + +def _decode_size(what, desc): + exponent = what & 0x0F + if exponent > 9: + raise dns.exception.SyntaxError("bad %s exponent" % desc) + base = (what & 0xF0) >> 4 + if base > 9: + raise dns.exception.SyntaxError("bad %s base" % desc) + return int(base) * pow(10, exponent) + +class LOC(dns.rdata.Rdata): + """LOC record + + @ivar latitude: latitude + @type latitude: (int, int, int, int) tuple specifying the degrees, minutes, + seconds, and milliseconds of the coordinate. + @ivar longitude: longitude + @type longitude: (int, int, int, int) tuple specifying the degrees, + minutes, seconds, and milliseconds of the coordinate. + @ivar altitude: altitude + @type altitude: float + @ivar size: size of the sphere + @type size: float + @ivar horizontal_precision: horizontal precision + @type horizontal_precision: float + @ivar vertical_precision: vertical precision + @type vertical_precision: float + @see: RFC 1876""" + + __slots__ = ['latitude', 'longitude', 'altitude', 'size', + 'horizontal_precision', 'vertical_precision'] + + def __init__(self, rdclass, rdtype, latitude, longitude, altitude, + size=1.0, hprec=10000.0, vprec=10.0): + """Initialize a LOC record instance. + + The parameters I{latitude} and I{longitude} may be either a 4-tuple + of integers specifying (degrees, minutes, seconds, milliseconds), + or they may be floating point values specifying the number of + degrees. The other parameters are floats.""" + + super(LOC, self).__init__(rdclass, rdtype) + if isinstance(latitude, int): + latitude = float(latitude) + if isinstance(latitude, float): + latitude = _float_to_tuple(latitude) + self.latitude = latitude + if isinstance(longitude, int): + longitude = float(longitude) + if isinstance(longitude, float): + longitude = _float_to_tuple(longitude) + self.longitude = longitude + self.altitude = float(altitude) + self.size = float(size) + self.horizontal_precision = float(hprec) + self.vertical_precision = float(vprec) + + def to_text(self, origin=None, relativize=True, **kw): + if self.latitude[0] > 0: + lat_hemisphere = 'N' + lat_degrees = self.latitude[0] + else: + lat_hemisphere = 'S' + lat_degrees = -1 * self.latitude[0] + if self.longitude[0] > 0: + long_hemisphere = 'E' + long_degrees = self.longitude[0] + else: + long_hemisphere = 'W' + long_degrees = -1 * self.longitude[0] + text = "%d %d %d.%03d %s %d %d %d.%03d %s %0.2fm" % ( + lat_degrees, self.latitude[1], self.latitude[2], self.latitude[3], + lat_hemisphere, long_degrees, self.longitude[1], self.longitude[2], + self.longitude[3], long_hemisphere, self.altitude / 100.0 + ) + + if self.size != 1.0 or self.horizontal_precision != 10000.0 or \ + self.vertical_precision != 10.0: + text += " %0.2fm %0.2fm %0.2fm" % ( + self.size / 100.0, self.horizontal_precision / 100.0, + self.vertical_precision / 100.0 + ) + return text + + def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): + latitude = [0, 0, 0, 0] + longitude = [0, 0, 0, 0] + size = 1.0 + hprec = 10000.0 + vprec = 10.0 + + latitude[0] = tok.get_int() + t = tok.get_string() + if t.isdigit(): + latitude[1] = int(t) + t = tok.get_string() + if '.' in t: + (seconds, milliseconds) = t.split('.') + if not seconds.isdigit(): + raise dns.exception.SyntaxError('bad latitude seconds value') + latitude[2] = int(seconds) + if latitude[2] >= 60: + raise dns.exception.SyntaxError('latitude seconds >= 60') + l = len(milliseconds) + if l == 0 or l > 3 or not milliseconds.isdigit(): + raise dns.exception.SyntaxError('bad latitude milliseconds value') + if l == 1: + m = 100 + elif l == 2: + m = 10 + else: + m = 1 + latitude[3] = m * int(milliseconds) + t = tok.get_string() + elif t.isdigit(): + latitude[2] = int(t) + t = tok.get_string() + if t == 'S': + latitude[0] *= -1 + elif t != 'N': + raise dns.exception.SyntaxError('bad latitude hemisphere value') + + longitude[0] = tok.get_int() + t = tok.get_string() + if t.isdigit(): + longitude[1] = int(t) + t = tok.get_string() + if '.' in t: + (seconds, milliseconds) = t.split('.') + if not seconds.isdigit(): + raise dns.exception.SyntaxError('bad longitude seconds value') + longitude[2] = int(seconds) + if longitude[2] >= 60: + raise dns.exception.SyntaxError('longitude seconds >= 60') + l = len(milliseconds) + if l == 0 or l > 3 or not milliseconds.isdigit(): + raise dns.exception.SyntaxError('bad longitude milliseconds value') + if l == 1: + m = 100 + elif l == 2: + m = 10 + else: + m = 1 + longitude[3] = m * int(milliseconds) + t = tok.get_string() + elif t.isdigit(): + longitude[2] = int(t) + t = tok.get_string() + if t == 'W': + longitude[0] *= -1 + elif t != 'E': + raise dns.exception.SyntaxError('bad longitude hemisphere value') + + t = tok.get_string() + if t[-1] == 'm': + t = t[0 : -1] + altitude = float(t) * 100.0 # m -> cm + + token = tok.get().unescape() + if not token.is_eol_or_eof(): + value = token.value + if value[-1] == 'm': + value = value[0 : -1] + size = float(value) * 100.0 # m -> cm + token = tok.get().unescape() + if not token.is_eol_or_eof(): + value = token.value + if value[-1] == 'm': + value = value[0 : -1] + hprec = float(value) * 100.0 # m -> cm + token = tok.get().unescape() + if not token.is_eol_or_eof(): + value = token.value + if value[-1] == 'm': + value = value[0 : -1] + vprec = float(value) * 100.0 # m -> cm + tok.get_eol() + + return cls(rdclass, rdtype, latitude, longitude, altitude, + size, hprec, vprec) + + from_text = classmethod(from_text) + + def to_wire(self, file, compress = None, origin = None): + if self.latitude[0] < 0: + sign = -1 + degrees = -1 * self.latitude[0] + else: + sign = 1 + degrees = self.latitude[0] + milliseconds = (degrees * 3600000 + + self.latitude[1] * 60000 + + self.latitude[2] * 1000 + + self.latitude[3]) * sign + latitude = 0x80000000 + milliseconds + if self.longitude[0] < 0: + sign = -1 + degrees = -1 * self.longitude[0] + else: + sign = 1 + degrees = self.longitude[0] + milliseconds = (degrees * 3600000 + + self.longitude[1] * 60000 + + self.longitude[2] * 1000 + + self.longitude[3]) * sign + longitude = 0x80000000 + milliseconds + altitude = int(self.altitude) + 10000000 + size = _encode_size(self.size, "size") + hprec = _encode_size(self.horizontal_precision, "horizontal precision") + vprec = _encode_size(self.vertical_precision, "vertical precision") + wire = struct.pack("!BBBBIII", 0, size, hprec, vprec, latitude, + longitude, altitude) + file.write(wire) + + def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): + (version, size, hprec, vprec, latitude, longitude, altitude) = \ + struct.unpack("!BBBBIII", wire[current : current + rdlen]) + if latitude > 0x80000000: + latitude = float(latitude - 0x80000000) / 3600000 + else: + latitude = -1 * float(0x80000000 - latitude) / 3600000 + if latitude < -90.0 or latitude > 90.0: + raise dns.exception.FormError("bad latitude") + if longitude > 0x80000000: + longitude = float(longitude - 0x80000000) / 3600000 + else: + longitude = -1 * float(0x80000000 - longitude) / 3600000 + if longitude < -180.0 or longitude > 180.0: + raise dns.exception.FormError("bad longitude") + altitude = float(altitude) - 10000000.0 + size = _decode_size(size, "size") + hprec = _decode_size(hprec, "horizontal precision") + vprec = _decode_size(vprec, "vertical precision") + return cls(rdclass, rdtype, latitude, longitude, altitude, + size, hprec, vprec) + + from_wire = classmethod(from_wire) + + def _cmp(self, other): + f = io.BytesIO() + self.to_wire(f) + wire1 = f.getvalue() + f.seek(0) + f.truncate() + other.to_wire(f) + wire2 = f.getvalue() + f.close() + + return dns.util.cmp(wire1, wire2) + + def _get_float_latitude(self): + return _tuple_to_float(self.latitude) + + def _set_float_latitude(self, value): + self.latitude = _float_to_tuple(value) + + float_latitude = property(_get_float_latitude, _set_float_latitude, + doc="latitude as a floating point value") + + def _get_float_longitude(self): + return _tuple_to_float(self.longitude) + + def _set_float_longitude(self, value): + self.longitude = _float_to_tuple(value) + + float_longitude = property(_get_float_longitude, _set_float_longitude, + doc="longitude as a floating point value") diff -Naur dnspython-orig/dnspython3-1.11.1/tests/dnssec.py dnspython/dnspython3-1.11.1/tests/dnssec.py --- dnspython-orig/dnspython3-1.11.1/tests/dnssec.py 2013-03-31 06:35:33.000000000 -0400 +++ dnspython/dnspython3-1.11.1/tests/dnssec.py 2014-02-18 18:36:33.492753557 -0500 @@ -97,6 +97,40 @@ example_ds_sha256 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, '18673 3 2 eb8344cbbf07c9d3d3d6c81d10c76653e28d8611a65e639ef8f716e4e4e5d913') +when3 = 1379801800 + +abs_ecdsa256_keys = { abs_example : + dns.rrset.from_text('example.', 86400, 'IN', 'DNSKEY', + "256 3 13 +3ss1sCpdARVA61DJigEsL/8quo2a8MszKtn2gkkfxgzFs8S2UHtpb4N fY+XFmNW+JK6MsCkI3jHYN8eEQUgMw==", + "257 3 13 eJCEVH7AS3wnoaQpaNlAXH0W8wxymtT9P6P3qjN2ZCV641ED8pF7wZ5V yWfOpgTs6oaZevbJgehl/GaRPUgVyQ==") + } + +abs_ecdsa256_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 4 10800 3600 604800 86400') + +abs_other_ecdsa256_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') + +abs_ecdsa256_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', + "SOA 13 1 86400 20130921221753 20130921221638 7460 example. Sm09SOGz1ULB5D/duwdE2Zpn8bWbVBM77H6N1wPkc42LevvVO+kZEjpq 2nq4GOMJcih52667GIAbMrwmU5P2MQ==") + +when4 = 1379804850 + +abs_ecdsa384_keys = { abs_example : + dns.rrset.from_text('example.', 86400, 'IN', 'DNSKEY', + "256 3 14 1bG8qWviKNXQX3BIuG6/T5jrP1FISiLW/8qGF6BsM9DQtWYhhZUA3Owr OAEiyHAhQwjkN2kTvWiAYoPN80Ii+5ff9/atzY4F9W50P4l75Dj9PYrL HN/hLUgWMNVc9pvA", + "257 3 14 mSub2n0KRt6u2FaD5XJ3oQu0R4XvB/9vUJcyW6+oo0y+KzfQeTdkf1ro ZMVKoyWXW9zUKBYGJpMUIdbAxzrYi7f5HyZ3yDpBFz1hw9+o3CX+gtgb +RyhHfJDwwFXBid9") + } + +abs_ecdsa384_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86400') + +abs_other_ecdsa384_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') + +abs_ecdsa384_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', + "SOA 14 1 86400 20130929021229 20130921230729 63571 example. CrnCu34EeeRz0fEhL9PLlwjpBKGYW8QjBjFQTwd+ViVLRAS8tNkcDwQE NhSV89NEjj7ze1a/JcCfcJ+/mZgnvH4NHLNg3Tf6KuLZsgs2I4kKQXEk 37oIHravPEOlGYNI") + class DNSSECValidatorTestCase(unittest.TestCase): def testAbsoluteRSAGood(self): @@ -143,6 +177,35 @@ ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA256') self.assertTrue(ds == example_ds_sha256) + @unittest.skipIf(not dns.dnssec._have_ecdsa, + "python ECDSA can not be imported") + def testAbsoluteECDSA256Good(self): + dns.dnssec.validate(abs_ecdsa256_soa, abs_ecdsa256_soa_rrsig, + abs_ecdsa256_keys, None, when3) + + @unittest.skipIf(not dns.dnssec._have_ecdsa, + "python ECDSA can not be imported") + def testAbsoluteECDSA256Bad(self): + def bad(): + dns.dnssec.validate(abs_other_ecdsa256_soa, abs_ecdsa256_soa_rrsig, + abs_ecdsa256_keys, None, when3) + self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) + + @unittest.skipIf(not dns.dnssec._have_ecdsa, + "python ECDSA can not be imported") + def testAbsoluteECDSA384Good(self): + dns.dnssec.validate(abs_ecdsa384_soa, abs_ecdsa384_soa_rrsig, + abs_ecdsa384_keys, None, when4) + + @unittest.skipIf(not dns.dnssec._have_ecdsa, + "python ECDSA can not be imported") + def testAbsoluteECDSA384Bad(self): + def bad(): + dns.dnssec.validate(abs_other_ecdsa384_soa, abs_ecdsa384_soa_rrsig, + abs_ecdsa384_keys, None, when4) + self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) + + if __name__ == '__main__': import_ok = False try: diff -Naur dnspython-orig/dnspython3-1.11.1/tests/dnssec.py.orig dnspython/dnspython3-1.11.1/tests/dnssec.py.orig --- dnspython-orig/dnspython3-1.11.1/tests/dnssec.py.orig 1969-12-31 19:00:00.000000000 -0500 +++ dnspython/dnspython3-1.11.1/tests/dnssec.py.orig 2014-02-18 18:36:33.492753557 -0500 @@ -0,0 +1,156 @@ +# Copyright (C) 2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.dnssec +import dns.name +import dns.rdata +import dns.rdataclass +import dns.rdatatype +import dns.rrset + +abs_dnspython_org = dns.name.from_text('dnspython.org') + +abs_keys = { abs_dnspython_org : + dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'DNSKEY', + '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', + '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF') + } + +abs_keys_duplicate_keytag = { abs_dnspython_org : + dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'DNSKEY', + '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', + '256 3 5 AwEAAdSSg++++THIS/IS/NOT/THE/CORRECT/KEY++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ AaOSydAF', + '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF') + } + +rel_keys = { dns.name.empty : + dns.rrset.from_text('@', 3600, 'IN', 'DNSKEY', + '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', + '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF') + } + +when = 1290250287 + +abs_soa = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'SOA', + 'howl.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600') + +abs_other_soa = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'SOA', + 'foo.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600') + +abs_soa_rrsig = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'RRSIG', + 'SOA 5 2 3600 20101127004331 20101119213831 61695 dnspython.org. sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=') + +rel_soa = dns.rrset.from_text('@', 3600, 'IN', 'SOA', + 'howl hostmaster 2010020047 3600 1800 604800 3600') + +rel_other_soa = dns.rrset.from_text('@', 3600, 'IN', 'SOA', + 'foo hostmaster 2010020047 3600 1800 604800 3600') + +rel_soa_rrsig = dns.rrset.from_text('@', 3600, 'IN', 'RRSIG', + 'SOA 5 2 3600 20101127004331 20101119213831 61695 @ sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=') + +sep_key = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DNSKEY, + '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=') + +good_ds = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, + '57349 5 2 53A79A3E7488AB44FFC56B2D1109F0699D1796DD977E72108B841F96 E47D7013') + +when2 = 1290425644 + +abs_example = dns.name.from_text('example') + +abs_dsa_keys = { abs_example : + dns.rrset.from_text('example.', 86400, 'IN', 'DNSKEY', + '257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X', + '256 3 3 CJE1yb9YRQiw5d2xZrMUMR+cGCTt1bp1KDCefmYKmS+Z1+q9f42ETVhx JRiQwXclYwmxborzIkSZegTNYIV6mrYwbNB27Q44c3UGcspb3PiOw5TC jNPRYEcdwGvDZ2wWy+vkSV/S9tHXY8O6ODiE6abZJDDg/RnITyi+eoDL R3KZ5n/V1f1T1b90rrV6EewhBGQJpQGDogaXb2oHww9Tm6NfXyo7SoMM pbwbzOckXv+GxRPJIQNSF4D4A9E8XCksuzVVdE/0lr37+uoiAiPia38U 5W2QWe/FJAEPLjIp2eTzf0TrADc1pKP1wrA2ASpdzpm/aX3IB5RPp8Ew S9U72eBFZJAUwg635HxJVxH1maG6atzorR566E+e0OZSaxXS9o1o6QqN 3oPlYLGPORDiExilKfez3C/x/yioOupW9K5eKF0gmtaqrHX0oq9s67f/ RIM2xVaKHgG9Vf2cgJIZkhv7sntujr+E4htnRmy9P9BxyFxsItYxPI6Z bzygHAZpGhlI/7ltEGlIwKxyTK3ZKBm67q7B') + } + +abs_dsa_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86400') + +abs_other_dsa_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', + 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') + +abs_dsa_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', + 'SOA 3 1 86400 20101129143231 20101122112731 42088 example. CGul9SuBofsktunV8cJs4eRs6u+3NCS3yaPKvBbD+pB2C76OUXDZq9U=') + +example_sep_key = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DNSKEY, + '257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X') + +example_ds_sha1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, + '18673 3 1 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7') + +example_ds_sha256 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, + '18673 3 2 eb8344cbbf07c9d3d3d6c81d10c76653e28d8611a65e639ef8f716e4e4e5d913') + +class DNSSECValidatorTestCase(unittest.TestCase): + + def testAbsoluteRSAGood(self): + dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys, None, when) + + def testDuplicateKeytag(self): + dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys_duplicate_keytag, None, when) + + def testAbsoluteRSABad(self): + def bad(): + dns.dnssec.validate(abs_other_soa, abs_soa_rrsig, abs_keys, None, + when) + self.assertRaises(dns.dnssec.ValidationFailure, bad) + + def testRelativeRSAGood(self): + dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys, + abs_dnspython_org, when) + + def testRelativeRSABad(self): + def bad(): + dns.dnssec.validate(rel_other_soa, rel_soa_rrsig, rel_keys, + abs_dnspython_org, when) + self.assertRaises(dns.dnssec.ValidationFailure, bad) + + def testMakeSHA256DS(self): + ds = dns.dnssec.make_ds(abs_dnspython_org, sep_key, 'SHA256') + self.assertTrue(ds == good_ds) + + def testAbsoluteDSAGood(self): + dns.dnssec.validate(abs_dsa_soa, abs_dsa_soa_rrsig, abs_dsa_keys, None, + when2) + + def testAbsoluteDSABad(self): + def bad(): + dns.dnssec.validate(abs_other_dsa_soa, abs_dsa_soa_rrsig, + abs_dsa_keys, None, when2) + self.assertRaises(dns.dnssec.ValidationFailure, bad) + + def testMakeExampleSHA1DS(self): + ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA1') + self.assertTrue(ds == example_ds_sha1) + + def testMakeExampleSHA256DS(self): + ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA256') + self.assertTrue(ds == example_ds_sha256) + +if __name__ == '__main__': + import_ok = False + try: + import Crypto.Util.number + import_ok = True + except: + pass + if import_ok: + unittest.main() + else: + print('skipping DNSSEC tests because pycrypto is not installed') diff -Naur dnspython-orig/dnspython3-1.11.1/tests/rdtypeanyloc.py dnspython/dnspython3-1.11.1/tests/rdtypeanyloc.py --- dnspython-orig/dnspython3-1.11.1/tests/rdtypeanyloc.py 1969-12-31 19:00:00.000000000 -0500 +++ dnspython/dnspython3-1.11.1/tests/rdtypeanyloc.py 2014-02-18 18:36:33.492753557 -0500 @@ -0,0 +1,68 @@ +# Copyright (C) 2014 Red Hat, Inc. +# Author: Petr Spacek +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import unittest + +import dns.rrset +import dns.rdtypes.ANY.LOC + +class RdtypeAnyLocTestCase(unittest.TestCase): + + def testEqual1(self): + '''Test default values for size, horizontal and vertical precision.''' + r1 = dns.rrset.from_text('foo', 300, 'IN', 'LOC', + '49 11 42.400 N 16 36 29.600 E 227.64m') + r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', + '49 11 42.400 N 16 36 29.600 E 227.64m ' + '1.00m 10000.00m 10.00m') + self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) + + def testEqual2(self): + '''Test default values for size, horizontal and vertical precision.''' + r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), + (16, 36, 29, 600), 22764.0) # centimeters + r2 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), + (16, 36, 29, 600), 22764.0, # centimeters + 100.0, 1000000.00, 1000.0) # centimeters + self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) + + def testEqual3(self): + '''Test size, horizontal and vertical precision parsers: 100 cm == 1 m. + + Parsers in from_text() and __init__() have to produce equal results.''' + r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), + (16, 36, 29, 600), 22764.0, + 200.0, 1000.00, 200.0) # centimeters + r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', + '49 11 42.400 N 16 36 29.600 E 227.64m ' + '2.00m 10.00m 2.00m')[0] + self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) + + def testEqual4(self): + '''Test size, horizontal and vertical precision parsers without unit. + + Parsers in from_text() and __init__() have produce equal result + for values with and without trailing "m".''' + r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), + (16, 36, 29, 600), 22764.0, + 200.0, 1000.00, 200.0) # centimeters + r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', + '49 11 42.400 N 16 36 29.600 E 227.64 ' + '2 10 2')[0] # meters without explicit unit + self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) + +if __name__ == '__main__': + unittest.main()