]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
allow TSIG key to be added to message structure after parsing
authorMatthijs Mekking <matthijs@isc.org>
Tue, 29 Jan 2019 17:10:27 +0000 (18:10 +0100)
committerEvan Hunt <each@isc.org>
Wed, 30 Jan 2019 20:11:23 +0000 (12:11 -0800)
up until now, message->tsigkey could only be set during parsing
of the request, but gss-tsig allows one to be created afterward.

lib/dns/include/dns/message.h
lib/dns/message.c
lib/dns/tkey.c
lib/dns/tsig.c

index c467eec56a35db5f0221827ae3bbd00c8e62c285..c73beaa19e70c71f5d28b2486b8649902d7db8e1 100644 (file)
@@ -178,7 +178,7 @@ typedef int dns_messagetextflag_t;
 #define DNS_MESSAGERENDER_PARTIAL      0x0002  /*%< allow a partial rdataset */
 #define DNS_MESSAGERENDER_OMITDNSSEC   0x0004  /*%< omit DNSSEC records */
 #define DNS_MESSAGERENDER_PREFER_A     0x0008  /*%< prefer A records in
-                                                     additional section. */
+                                                    additional section. */
 #define DNS_MESSAGERENDER_PREFER_AAAA  0x0010  /*%< prefer AAAA records in
                                                  additional section. */
 #define DNS_MESSAGERENDER_FILTER_AAAA  0x0020  /*%< filter AAAA records */
index 24156df9572e2eca9e51df5d11ca0286bb786449..13f29e0e044764b15894d80544c759607ad5d6eb 100644 (file)
@@ -2858,7 +2858,6 @@ dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
         */
 
        REQUIRE(DNS_MESSAGE_VALID(msg));
-       REQUIRE(msg->state == DNS_SECTION_ANY);
 
        if (key == NULL && msg->tsigkey != NULL) {
                if (msg->sig_reserved != 0) {
index 8dadb2bb7dd77e7a9f297c0b45c6c8abc17a1ed9..f4447f3e442c4553a8becb7a071bbd5f04af037e 100644 (file)
@@ -461,7 +461,7 @@ process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
 }
 
 static isc_result_t
-process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
+process_gsstkey(dns_message_t *msg, dns_name_t *name, dns_rdata_tkey_t *tkeyin,
                dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout,
                dns_tsig_keyring_t *ring)
 {
@@ -479,7 +479,7 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
         * You have to define either a gss credential (principal) to
         * accept with tkey-gssapi-credential, or you have to
         * configure a specific keytab (with tkey-gssapi-keytab) in
-        * order to use gsstkey
+        * order to use gsstkey.
         */
        if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) {
                tkey_log("process_gsstkey(): no tkey-gssapi-credential "
@@ -553,7 +553,7 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
                RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
                                                 dstkey, true, principal,
                                                 now, expire, ring->mctx, ring,
-                                                NULL));
+                                                &tsigkey));
                dst_key_free(&dstkey);
                tkeyout->inception = now;
                tkeyout->expire = expire;
@@ -588,6 +588,15 @@ process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
 
        tkey_log("process_gsstkey(): dns_tsigerror_noerror");   /* XXXSRA */
 
+       /*
+        * We found a TKEY to respond with.  If the request is not TSIG signed,
+        * we need to make sure the response is signed (see RFC 3645, Section
+        * 2.2).
+        */
+       if (tsigkey != NULL && msg->tsigkey == NULL && msg->sig0key == NULL) {
+               dns_message_settsigkey(msg, tsigkey);
+       }
+
        return (ISC_R_SUCCESS);
 
 failure:
@@ -721,9 +730,9 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
        result = dns_message_signer(msg, &tsigner);
        if (result != ISC_R_SUCCESS) {
                if (tkeyin.mode == DNS_TKEYMODE_GSSAPI &&
-                   result == ISC_R_NOTFOUND)
-                      signer = NULL;
-               else {
+                   result == ISC_R_NOTFOUND) {
+                       signer = NULL;
+               else {
                        tkey_log("dns_tkey_processquery: query was not "
                                 "properly signed - rejecting");
                        result = DNS_R_FORMERR;
@@ -831,7 +840,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
                        break;
                case DNS_TKEYMODE_GSSAPI:
                        tkeyout.error = dns_rcode_noerror;
-                       RETERR(process_gsstkey(keyname, &tkeyin, tctx,
+                       RETERR(process_gsstkey(msg, keyname, &tkeyin, tctx,
                                               &tkeyout, ring));
                        break;
                case DNS_TKEYMODE_DELETE:
@@ -848,6 +857,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
        }
 
  failure_with_tkey:
+
        dns_rdata_init(&rdata);
        isc_buffer_init(&tkeyoutbuf, tkeyoutdata, sizeof(tkeyoutdata));
        result = dns_rdata_fromstruct(&rdata, tkeyout.common.rdclass,
@@ -881,6 +891,7 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
        return (ISC_R_SUCCESS);
 
  failure:
+
        if (freetkeyin)
                dns_rdata_freestruct(&tkeyin);
        if (!ISC_LIST_EMPTY(namelist))
index 9864569514df978caef4ee9f0355344a3bdd500c..d53ae87528cd2e54b50debb048702dc5f707eb9a 100644 (file)
@@ -768,15 +768,15 @@ dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
 
 isc_result_t
 dns_tsig_sign(dns_message_t *msg) {
-       dns_tsigkey_t *key;
+       dns_tsigkey_t *key = NULL;
        dns_rdata_any_tsig_t tsig, querytsig;
        unsigned char data[128];
        isc_buffer_t databuf, sigbuf;
-       isc_buffer_t *dynbuf;
+       isc_buffer_t *dynbuf = NULL;
        dns_name_t *owner;
        dns_rdata_t *rdata = NULL;
-       dns_rdatalist_t *datalist;
-       dns_rdataset_t *dataset;
+       dns_rdatalist_t *datalist = NULL;
+       dns_rdataset_t *dataset = NULL;
        isc_region_t r;
        isc_stdtime_t now;
        isc_mem_t *mctx;
@@ -791,13 +791,15 @@ dns_tsig_sign(dns_message_t *msg) {
        REQUIRE(VALID_TSIG_KEY(key));
 
        /*
-        * If this is a response, there should be a query tsig.
+        * If this is a response, there should be a TSIG in the query with the
+        * the exception if this is a TKEY request (see RFC 3645, Section 2.2).
         */
        response = is_response(msg);
-       if (response && msg->querytsig == NULL)
-               return (DNS_R_EXPECTEDTSIG);
-
-       dynbuf = NULL;
+       if (response && msg->querytsig == NULL) {
+               if (msg->tkey != 1) {
+                       return (DNS_R_EXPECTEDTSIG);
+               }
+       }
 
        mctx = msg->mctx;
 
@@ -853,9 +855,15 @@ dns_tsig_sign(dns_message_t *msg) {
                        return (ret);
 
                /*
-                * If this is a response, digest the request's MAC.
+                * If this is a response, and if there was a TSIG in
+                * the query, digest the request's MAC.
+                *
+                * (Note: querytsig should be non-NULL for all
+                * responses except TKEY responses. Those may be signed
+                * with the newly-negotiated TSIG key even if the query
+                * wasn't signed.)
                 */
-               if (response) {
+               if (response && msg->querytsig != NULL) {
                        dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
 
                        INSIST(msg->verified_sig);