summaryrefslogtreecommitdiff
path: root/source4/dns_server
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2016-05-23 19:09:05 +0200
committerGarming Sam <garming@samba.org>2016-06-16 00:06:27 +0200
commit8ed125e8bb13904638f8506e860c169f788e8ee9 (patch)
tree22a477018a921fbad2715b01575aa670a5cdeeac /source4/dns_server
parentbea4aec521576576b8dc55065f11c6c5025d9c4f (diff)
downloadsamba-8ed125e8bb13904638f8506e860c169f788e8ee9.tar.gz
s4/dns_server: include request MAC in TSIG response MAC calculation
According to RFC 2845 "4.2 TSIG on Answers", when the request is signed, the request MAC must be included in the response MAC calculation. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11520 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Diffstat (limited to 'source4/dns_server')
-rw-r--r--source4/dns_server/dns_crypto.c37
1 files changed, 34 insertions, 3 deletions
diff --git a/source4/dns_server/dns_crypto.c b/source4/dns_server/dns_crypto.c
index 502887fec88..a8d76a4bb26 100644
--- a/source4/dns_server/dns_crypto.c
+++ b/source4/dns_server/dns_crypto.c
@@ -243,12 +243,14 @@ WERROR dns_sign_tsig(struct dns_server *dns,
time_t current_time = time(NULL);
DATA_BLOB packet_blob, tsig_blob, sig;
uint8_t *buffer = NULL;
+ uint8_t *p = NULL;
size_t buffer_len = 0;
struct dns_server_tkey * tkey = NULL;
struct dns_res_rec *tsig = talloc_zero(mem_ctx, struct dns_res_rec);
struct dns_fake_tsig_rec *check_rec = talloc_zero(mem_ctx,
struct dns_fake_tsig_rec);
+ size_t mac_size = 0;
if (tsig == NULL) {
return WERR_NOMEM;
@@ -298,15 +300,44 @@ WERROR dns_sign_tsig(struct dns_server *dns,
return DNS_ERR(SERVER_FAILURE);
}
- buffer_len = packet_blob.length + tsig_blob.length;
+ if (state->tsig != NULL) {
+ mac_size = state->tsig->rdata.tsig_record.mac_size;
+ }
+
+ buffer_len = mac_size;
+
+ buffer_len += packet_blob.length;
+ if (buffer_len < packet_blob.length) {
+ return WERR_INVALID_PARAM;
+ }
+ buffer_len += tsig_blob.length;
+ if (buffer_len < tsig_blob.length) {
+ return WERR_INVALID_PARAM;
+ }
+
buffer = talloc_zero_array(mem_ctx, uint8_t, buffer_len);
if (buffer == NULL) {
return WERR_NOMEM;
}
- memcpy(buffer, packet_blob.data, packet_blob.length);
- memcpy(buffer+packet_blob.length, tsig_blob.data, tsig_blob.length);
+ p = buffer;
+
+ /*
+ * RFC 2845 "4.2 TSIG on Answers", how to lay out the buffer
+ * that we're going to sign:
+ * 1. MAC of request (if present)
+ * 2. Outgoing packet
+ * 3. TSIG record
+ */
+ if (mac_size > 0) {
+ memcpy(p, state->tsig->rdata.tsig_record.mac, mac_size);
+ p += mac_size;
+ }
+
+ memcpy(p, packet_blob.data, packet_blob.length);
+ p += packet_blob.length;
+ memcpy(p, tsig_blob.data, tsig_blob.length);
status = gensec_sign_packet(tkey->gensec, mem_ctx, buffer, buffer_len,
buffer, buffer_len, &sig);