s4/dns_server: split out function that does the MAC computation
authorRalph Boehme <slow@samba.org>
Mon, 30 May 2016 14:03:33 +0000 (16:03 +0200)
committerKarolin Seeger <kseeger@samba.org>
Thu, 23 Jun 2016 10:10:22 +0000 (12:10 +0200)
Split out function that does the MAC computation from the TSIG record
creating function. This will later simplify the code when creating error
responsed to TSIG requests with bad MACs where we have to add the TSIG
record with an empty MAC.

No functional behaviour change besides hard coding "gss-tsig" algorithm
name: later when sending a TSIG error response for a TKEY request with a
bad keyname, we won't have a tkey to fetch the algorithm name from.

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>
(cherry picked from commit 830316ce84c6f4994841a1c68e60d90225a2963d)

source4/dns_server/dns_crypto.c

index a8d76a4bb2691e729cd223a4d099849577fdd2dc..a49b23c8f457d241b0770337e569dec11a5394f5 100644 (file)
@@ -231,41 +231,27 @@ WERROR dns_verify_tsig(struct dns_server *dns,
        return WERR_OK;
 }
 
-WERROR dns_sign_tsig(struct dns_server *dns,
-                    TALLOC_CTX *mem_ctx,
-                    struct dns_request_state *state,
-                    struct dns_name_packet *packet,
-                    uint16_t error)
+static WERROR dns_tsig_compute_mac(TALLOC_CTX *mem_ctx,
+                                  struct dns_request_state *state,
+                                  struct dns_name_packet *packet,
+                                  struct dns_server_tkey *tkey,
+                                  time_t current_time,
+                                  DATA_BLOB *_psig)
 {
-       WERROR werror;
        NTSTATUS status;
        enum ndr_err_code ndr_err;
-       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;
-       }
-
        if (check_rec == NULL) {
                return WERR_NOMEM;
        }
 
-       tkey = dns_find_tkey(dns->tkeys, state->key_name);
-       if (tkey == NULL) {
-               /* FIXME: read up on what to do when we can't find a key */
-               return WERR_OK;
-       }
-
        /* first build and verify check packet */
        check_rec->name = talloc_strdup(check_rec, tkey->name);
        if (check_rec->name == NULL) {
@@ -345,19 +331,54 @@ WERROR dns_sign_tsig(struct dns_server *dns,
                return ntstatus_to_werror(status);
        }
 
-       tsig->name = talloc_strdup(tsig, check_rec->name);
+       *_psig = sig;
+       return WERR_OK;
+}
+
+WERROR dns_sign_tsig(struct dns_server *dns,
+                    TALLOC_CTX *mem_ctx,
+                    struct dns_request_state *state,
+                    struct dns_name_packet *packet,
+                    uint16_t error)
+{
+       WERROR werror;
+       time_t current_time = time(NULL);
+       struct dns_server_tkey *tkey = NULL;
+       struct dns_res_rec *tsig = NULL;
+       DATA_BLOB sig = (DATA_BLOB) {
+               .data = NULL,
+               .length = 0
+       };
+
+       tsig = talloc_zero(mem_ctx, struct dns_res_rec);
+       if (tsig == NULL) {
+               return WERR_NOMEM;
+       }
+
+       tkey = dns_find_tkey(dns->tkeys, state->key_name);
+       if (tkey == NULL) {
+               /* FIXME: read up on what to do when we can't find a key */
+               return WERR_OK;
+       }
+
+       werror = dns_tsig_compute_mac(mem_ctx, state, packet,
+                                     tkey, current_time, &sig);
+       if (!W_ERROR_IS_OK(werror)) {
+               return werror;
+       }
+
+       tsig->name = talloc_strdup(tsig, state->key_name);
        if (tsig->name == NULL) {
                return WERR_NOMEM;
        }
-       tsig->rr_class = check_rec->rr_class;
+       tsig->rr_class = DNS_QCLASS_ANY;
        tsig->rr_type = DNS_QTYPE_TSIG;
        tsig->ttl = 0;
        tsig->length = UINT16_MAX;
-       tsig->rdata.tsig_record.algorithm_name = talloc_strdup(tsig,
-                       check_rec->algorithm_name);
-       tsig->rdata.tsig_record.time_prefix = check_rec->time_prefix;
-       tsig->rdata.tsig_record.time = check_rec->time;
-       tsig->rdata.tsig_record.fudge = check_rec->fudge;
+       tsig->rdata.tsig_record.algorithm_name = talloc_strdup(tsig, "gss-tsig");
+       tsig->rdata.tsig_record.time_prefix = 0;
+       tsig->rdata.tsig_record.time = current_time;
+       tsig->rdata.tsig_record.fudge = 300;
        tsig->rdata.tsig_record.error = state->tsig_error;
        tsig->rdata.tsig_record.original_id = packet->id;
        tsig->rdata.tsig_record.other_size = 0;