diff --git a/lib/dns/include/dns/tsig.h b/lib/dns/include/dns/tsig.h index d267894d94..418cc1f7f2 100644 --- a/lib/dns/include/dns/tsig.h +++ b/lib/dns/include/dns/tsig.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: tsig.h,v 1.35 2000/08/25 01:06:39 bwelling Exp $ */ +/* $Id: tsig.h,v 1.36 2000/10/12 00:40:52 bwelling Exp $ */ #ifndef DNS_TSIG_H #define DNS_TSIG_H 1 @@ -37,6 +37,8 @@ extern dns_name_t *dns_tsig_hmacmd5_name; #define DNS_TSIG_HMACMD5_NAME dns_tsig_hmacmd5_name extern dns_name_t *dns_tsig_gssapi_name; #define DNS_TSIG_GSSAPI_NAME dns_tsig_gssapi_name +extern dns_name_t *dns_tsig_gssapims_name; +#define DNS_TSIG_GSSAPIMS_NAME dns_tsig_gssapims_name /* * Default fudge value. diff --git a/lib/dns/message.c b/lib/dns/message.c index f6ac195ea5..770adccb5d 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: message.c,v 1.151 2000/10/11 23:57:38 bwelling Exp $ */ +/* $Id: message.c,v 1.152 2000/10/12 00:40:48 bwelling Exp $ */ /*** *** Imports @@ -1149,8 +1149,9 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, if (msg->opcode != dns_opcode_update && rdtype != dns_rdatatype_tsig && rdtype != dns_rdatatype_opt - && rdtype != dns_rdatatype_key /* XXX in a TKEY query */ - && rdtype != dns_rdatatype_sig /* XXX SIG(0) */ + && rdtype != dns_rdatatype_key /* in a TKEY query */ + && rdtype != dns_rdatatype_sig /* SIG(0) */ + && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */ && msg->rdclass != rdclass) DO_FORMERR; @@ -1192,7 +1193,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, /* * A TKEY must be in the additional section if this * is a query, and the answer section if this is a - * response. + * response. Unless it's a Win2000 client. + * * Its class is ignored. */ dns_section_t tkeysection; @@ -1201,7 +1203,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, tkeysection = DNS_SECTION_ADDITIONAL; else tkeysection = DNS_SECTION_ANSWER; - if (sectionid != tkeysection) + if (sectionid != tkeysection && + sectionid != DNS_SECTION_ANSWER) DO_FORMERR; } diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c index de9fe1bd5e..b7fc1f37eb 100644 --- a/lib/dns/tkey.c +++ b/lib/dns/tkey.c @@ -16,7 +16,7 @@ */ /* - * $Id: tkey.c,v 1.53 2000/10/07 00:09:25 bwelling Exp $ + * $Id: tkey.c,v 1.54 2000/10/12 00:40:50 bwelling Exp $ */ #include @@ -105,7 +105,8 @@ dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp) { if (tctx->dhkey != NULL) dst_key_free(&tctx->dhkey); if (tctx->domain != NULL) { - dns_name_free(tctx->domain, mctx); + if (dns_name_dynamic(tctx->domain)) + dns_name_free(tctx->domain, mctx); isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t)); } isc_entropy_detach(&tctx->ectx); @@ -244,6 +245,12 @@ process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name, unsigned char *randomdata = NULL, secretdata[256]; isc_stdtime_t now; + if (tctx->dhkey == NULL) { + tkey_log("process_dhtkey: tkey-dhkey not defined"); + tkeyout->error = dns_tsigerror_badalg; + return (DNS_R_REFUSED); + } + if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) { tkey_log("process_dhtkey: algorithms other than " "hmac-md5 are not supported"); @@ -434,7 +441,8 @@ process_gsstkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name, if (tctx->gsscred == NULL) return (ISC_R_NOPERM); - if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME)) { + if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) && + !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) { tkeyout->error = dns_tsigerror_badalg; return (ISC_R_SUCCESS); } @@ -565,10 +573,19 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx, result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL, qname, dns_rdatatype_tkey, 0, &name, &tkeyset); if (result != ISC_R_SUCCESS) { - result = DNS_R_FORMERR; - tkey_log("dns_tkey_processquery: couldn't find a TKEY " - "matching the question"); - goto failure; + /* + * Try the answer section, since that's where Win2000 + * puts it. + */ + if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname, + dns_rdatatype_tkey, 0, &name, + &tkeyset) != ISC_R_SUCCESS) + { + result = DNS_R_FORMERR; + tkey_log("dns_tkey_processquery: couldn't find a TKEY " + "matching the question"); + goto failure; + } } result = dns_rdataset_first(tkeyset); if (result != ISC_R_SUCCESS) { @@ -675,6 +692,11 @@ dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx, goto failure; } } + if (tctx->domain == NULL) { + tkey_log("dns_tkey_processquery: tkey-domain not set"); + result = DNS_R_REFUSED; + goto failure; + } result = dns_name_concatenate(&prefix, tctx->domain, keyname, buf); dns_message_takebuffer(msg, &buf); @@ -1140,9 +1162,9 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, dns_name_t *gname, void *cred, void **context, dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring) { - dns_rdata_t rtkeyrdata; + dns_rdata_t rtkeyrdata, qtkeyrdata; dns_name_t *tkeyname; - dns_rdata_tkey_t rtkey; + dns_rdata_tkey_t rtkey, qtkey; isc_buffer_t outtoken; dst_key_t *dstkey = NULL; isc_region_t r; @@ -1156,16 +1178,18 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg, REQUIRE(*outkey == NULL); REQUIRE(ring != NULL); - UNUSED(qmsg); - if (rmsg->rcode != dns_rcode_noerror) return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode); RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER)); RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL)); + RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata, + DNS_SECTION_ADDITIONAL)); + RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL)); + if (rtkey.error != dns_rcode_noerror || rtkey.mode != DNS_TKEYMODE_GSSAPI || - !dns_name_equal(&rtkey.algorithm, DNS_TSIG_GSSAPI_NAME)) + !dns_name_equal(&rtkey.algorithm, &rtkey.algorithm)) { tkey_log("dns_tkey_processdhresponse: tkey mode invalid " "or error set"); diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 9677fdc6f5..28195fd7a1 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -16,7 +16,7 @@ */ /* - * $Id: tsig.c,v 1.92 2000/10/07 00:09:27 bwelling Exp $ + * $Id: tsig.c,v 1.93 2000/10/12 00:40:51 bwelling Exp $ * Principal Author: Brian Wellington */ @@ -47,7 +47,8 @@ #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR) #define algname_is_allocated(algname) \ ((algname) != dns_tsig_hmacmd5_name && \ - (algname) != dns_tsig_gssapi_name) + (algname) != dns_tsig_gssapi_name && \ + (algname) != dns_tsig_gssapims_name) #define BADTIMELEN 6 @@ -88,6 +89,22 @@ static struct dns_constname gsstsig = { dns_name_t *dns_tsig_gssapi_name = &gsstsig.name; +/* It's nice of Microsoft to conform to their own standard. */ +static struct dns_constname gsstsigms = { + { + DNS_NAME_MAGIC, + gsstsigms.const_ndata, 19, 4, + DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, + gsstsigms.const_offsets, NULL, + {(void *)-1, (void *)-1}, + {NULL, NULL} + }, + { "\003gss\011microsoft\003com" }, /* const_ndata */ + { 0, 4, 14, 18 } /* const_offsets */ +}; + +dns_name_t *dns_tsig_gssapims_name = &gsstsigms.name; + static isc_result_t tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg); @@ -120,6 +137,8 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, tkey->algorithm = DNS_TSIG_HMACMD5_NAME; else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) tkey->algorithm = DNS_TSIG_GSSAPI_NAME; + else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) + tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME; else { if (key != NULL) { ret = ISC_R_NOTIMPLEMENTED;