From: Matthijs Mekking Date: Tue, 29 Jan 2019 17:10:27 +0000 (+0100) Subject: allow TSIG key to be added to message structure after parsing X-Git-Tag: v9.12.4rc1~37^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=879fc0285edf135a78a71911a6d49746f6e67342;p=thirdparty%2Fbind9.git allow TSIG key to be added to message structure after parsing up until now, message->tsigkey could only be set during parsing of the request, but gss-tsig allows one to be created afterward. --- diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index c467eec56a3..c73beaa19e7 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -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 */ diff --git a/lib/dns/message.c b/lib/dns/message.c index 24156df9572..13f29e0e044 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -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) { diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c index 8dadb2bb7dd..f4447f3e442 100644 --- a/lib/dns/tkey.c +++ b/lib/dns/tkey.c @@ -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)) diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 9864569514d..d53ae87528c 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -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);