ef6d7f5b89
- Added LOC and ECDSA fixes from git (rhbz#1059594)
1672 lines
72 KiB
Diff
1672 lines
72 KiB
Diff
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 <halley@dnspython.org>
|
|
+
|
|
+ * 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 <halley@dnspython.org>
|
|
|
|
* (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 <pspacek@redhat.com>
|
|
+#
|
|
+# 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 <halley@dnspython.org>
|
|
+
|
|
+ * 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 <halley@dnspython.org>
|
|
|
|
* (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 <pspacek@redhat.com>
|
|
+#
|
|
+# 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()
|