summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Halley <halley@dnspython.org>2014-04-04 05:34:49 -0700
committerBob Halley <halley@dnspython.org>2014-04-04 05:36:11 -0700
commit2db54ba975ed5be22f92af105bb2bd6b0ccbbef1 (patch)
treebe94232990bd8600bef945af20cc1d3409a9f387
parent01e5a49816c1c6ffc9cf0a4676662193649a9380 (diff)
downloaddnspython-2db54ba975ed5be22f92af105bb2bd6b0ccbbef1.tar.gz
Responses to messages signed with TSIG were broken.
-rw-r--r--ChangeLog6
-rw-r--r--dns/message.py15
-rw-r--r--dns/tsig.py16
3 files changed, 33 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 2e48d9c..6654bb1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-04-04 Bob Halley <halley@dnspython.org>
+
+ * dns/message.py: Making a response didn't work correctly if the
+ query was signed with TSIG and we knew the key. Thanks to Jeffrey
+ Stiles for reporting the problem.
+
2013-12-11 Bob Halley <halley@dnspython.org>
* dns/query.py: Fix problems with the IXFR state machine which caused
diff --git a/dns/message.py b/dns/message.py
index 52c0eae..e523931 100644
--- a/dns/message.py
+++ b/dns/message.py
@@ -665,6 +665,10 @@ class _WireReader(object):
secret = self.message.keyring.get(absolute_name)
if secret is None:
raise UnknownTSIGKey("key '%s' unknown" % name)
+ self.message.keyname = absolute_name
+ (self.message.keyalgorithm, self.message.mac) = \
+ dns.tsig.get_algorithm_and_mac(self.wire, self.current,
+ rdlen)
self.message.tsig_ctx = \
dns.tsig.validate(self.wire,
absolute_name,
@@ -1071,7 +1075,8 @@ def make_query(qname, rdtype, rdclass = dns.rdataclass.IN, use_edns=None,
m.want_dnssec(want_dnssec)
return m
-def make_response(query, recursion_available=False, our_payload=8192):
+def make_response(query, recursion_available=False, our_payload=8192,
+ fudge=300):
"""Make a message which is a response for the specified query.
The message returned is really a response skeleton; it has all
of the infrastructure required of a response, but none of the
@@ -1088,6 +1093,8 @@ def make_response(query, recursion_available=False, our_payload=8192):
@param our_payload: payload size to advertise in EDNS responses; default
is 8192.
@type our_payload: int
+ @param fudge: TSIG time fudge; default is 300 seconds.
+ @type fudge: int
@rtype: dns.message.Message object"""
if query.flags & dns.flags.QR:
@@ -1100,8 +1107,8 @@ def make_response(query, recursion_available=False, our_payload=8192):
response.question = list(query.question)
if query.edns >= 0:
response.use_edns(0, 0, our_payload, query.payload)
- if not query.keyname is None:
- response.keyname = query.keyname
- response.keyring = query.keyring
+ if query.had_tsig:
+ response.use_tsig(query.keyring, query.keyname, fudge, None, 0, '',
+ query.keyalgorithm)
response.request_mac = query.mac
return response
diff --git a/dns/tsig.py b/dns/tsig.py
index 6e97dce..2dd4b42 100644
--- a/dns/tsig.py
+++ b/dns/tsig.py
@@ -221,3 +221,19 @@ def get_algorithm(algorithm):
except KeyError:
raise NotImplementedError("TSIG algorithm " + str(algorithm) +
" is not supported")
+
+def get_algorithm_and_mac(wire, tsig_rdata, tsig_rdlen):
+ """Return the tsig algorithm for the specified tsig_rdata
+ @raises FormError: The TSIG is badly formed.
+ """
+ current = tsig_rdata
+ (aname, used) = dns.name.from_wire(wire, current)
+ current = current + used
+ (upper_time, lower_time, fudge, mac_size) = \
+ struct.unpack("!HIHH", wire[current:current + 10])
+ current += 10
+ mac = wire[current:current + mac_size]
+ current += mac_size
+ if current > tsig_rdata + tsig_rdlen:
+ raise dns.exception.FormError
+ return (aname, mac)