diff options
Diffstat (limited to 'lib/dns/tsig.c')
-rw-r--r-- | lib/dns/tsig.c | 510 |
1 files changed, 242 insertions, 268 deletions
diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 858ebd30..71846724 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -16,13 +16,14 @@ */ /* - * $Id: tsig.c,v 1.61 2000/05/22 23:17:22 bwelling Exp $ + * $Id: tsig.c,v 1.71 2000/06/06 23:44:13 bwelling Exp $ * Principal Author: Brian Wellington */ #include <config.h> #include <stdlib.h> /* Required for abs(). */ +#include <isc/buffer.h> #include <isc/mem.h> #include <isc/once.h> #include <isc/string.h> /* Required for HP/UX (and others?) */ @@ -33,6 +34,7 @@ #include <dns/rdata.h> #include <dns/rdatalist.h> #include <dns/rdataset.h> +#include <dns/rdatastruct.h> #include <dns/result.h> #include <dns/tsig.h> @@ -57,12 +59,10 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, isc_stdtime_t expire, isc_mem_t *mctx, dns_tsig_keyring_t *ring, dns_tsigkey_t **key) { - isc_buffer_t b, nameb; - char namestr[1025]; + isc_buffer_t b; isc_uint16_t alg; dns_tsigkey_t *tkey; isc_result_t ret; - isc_region_t r; REQUIRE(key == NULL || *key == NULL); REQUIRE(name != NULL); @@ -109,14 +109,6 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, else tkey->creator = NULL; - isc_buffer_init(&nameb, namestr, sizeof(namestr) - 1); - ret = dns_name_totext(name, ISC_FALSE, &nameb); - if (ret != ISC_R_SUCCESS) - goto cleanup_algorithm; - - isc_buffer_usedregion(&nameb, &r); - namestr[r.length] = '\0'; - tkey->key = NULL; tkey->ring = NULL; if (length > 0) { @@ -124,7 +116,7 @@ dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, isc_buffer_init(&b, secret, length); isc_buffer_add(&b, length); - ret = dst_key_frombuffer(namestr, alg, + ret = dst_key_frombuffer(name, alg, DNS_KEYOWNER_ENTITY, DNS_KEYPROTO_DNSSEC, &b, mctx, &tkey->key); @@ -183,51 +175,58 @@ cleanup_key: return (ret); } +void +dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) { + REQUIRE(VALID_TSIG_KEY(source)); + REQUIRE(targetp != NULL && *targetp == NULL); + + isc_mutex_lock(&source->lock); + source->refs++; + isc_mutex_unlock(&source->lock); + *targetp = source; +} + static void -tsigkey_free(dns_tsigkey_t **key) { - dns_tsigkey_t *tkey; +tsigkey_free(dns_tsigkey_t *key) { dns_tsig_keyring_t *ring; - REQUIRE(key != NULL); - REQUIRE(VALID_TSIG_KEY(*key)); - tkey = *key; - *key = NULL; - ring = tkey->ring; + REQUIRE(VALID_TSIG_KEY(key)); + ring = key->ring; - tkey->magic = 0; - if (tkey->key != NULL) { + key->magic = 0; + if (key->key != NULL) { isc_rwlock_lock(&ring->lock, isc_rwlocktype_write); - ISC_LIST_UNLINK(ring->keys, tkey, link); + ISC_LIST_UNLINK(ring->keys, key, link); isc_rwlock_unlock(&ring->lock, isc_rwlocktype_write); } - dns_name_free(&tkey->name, tkey->mctx); - dns_name_free(&tkey->algorithm, tkey->mctx); - if (tkey->key != NULL) - dst_key_free(&tkey->key); - if (tkey->creator != NULL) { - dns_name_free(tkey->creator, tkey->mctx); - isc_mem_put(tkey->mctx, tkey->creator, sizeof(dns_name_t)); + dns_name_free(&key->name, key->mctx); + dns_name_free(&key->algorithm, key->mctx); + if (key->key != NULL) + dst_key_free(&key->key); + if (key->creator != NULL) { + dns_name_free(key->creator, key->mctx); + isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t)); } - isc_mem_put(tkey->mctx, tkey, sizeof(dns_tsigkey_t)); + isc_mem_put(key->mctx, key, sizeof(dns_tsigkey_t)); } void -dns_tsigkey_free(dns_tsigkey_t **key) { +dns_tsigkey_detach(dns_tsigkey_t **key) { dns_tsigkey_t *tkey; REQUIRE(key != NULL); REQUIRE(VALID_TSIG_KEY(*key)); tkey = *key; + *key = NULL; isc_mutex_lock(&tkey->lock); tkey->refs--; if (tkey->refs > 0 || (!tkey->deleted && tkey->key != NULL)) { isc_mutex_unlock(&tkey->lock); - *key = NULL; return; } isc_mutex_unlock(&tkey->lock); - tsigkey_free(key); + tsigkey_free(tkey); } void @@ -241,7 +240,7 @@ dns_tsigkey_setdeleted(dns_tsigkey_t *key) { isc_result_t dns_tsig_sign(dns_message_t *msg) { dns_tsigkey_t *key; - dns_rdata_any_tsig_t tsig; + dns_rdata_any_tsig_t tsig, querytsig; unsigned char data[128]; isc_buffer_t databuf, sigbuf; isc_buffer_t *dynbuf; @@ -251,14 +250,12 @@ dns_tsig_sign(dns_message_t *msg) { dns_rdataset_t *dataset; isc_region_t r, r2; isc_stdtime_t now; - dst_context_t ctx; isc_mem_t *mctx; + dst_context_t *ctx = NULL; isc_result_t ret; - isc_boolean_t algfreed = ISC_FALSE; REQUIRE(msg != NULL); - REQUIRE(VALID_TSIG_KEY(msg->tsigkey)); - REQUIRE(msg->tsig == NULL); + REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg))); /* * If this is a response, there should be a query tsig. @@ -269,16 +266,14 @@ dns_tsig_sign(dns_message_t *msg) { dynbuf = NULL; mctx = msg->mctx; - key = msg->tsigkey; + key = dns_message_gettsigkey(msg); tsig.mctx = mctx; tsig.common.rdclass = dns_rdataclass_any; tsig.common.rdtype = dns_rdatatype_tsig; ISC_LINK_INIT(&tsig.common, link); dns_name_init(&tsig.algorithm, NULL); - ret = dns_name_dup(&key->algorithm, mctx, &tsig.algorithm); - if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + dns_name_clone(&key->algorithm, &tsig.algorithm); isc_stdtime_get(&now); tsig.timesigned = now; @@ -318,27 +313,37 @@ dns_tsig_sign(dns_message_t *msg) { isc_buffer_t headerbuf; unsigned int sigsize; - ret = dst_key_sign(DST_SIGMODE_INIT, key->key, &ctx, NULL, - NULL); + ret = dst_context_create(key->key, mctx, &ctx); if (ret != ISC_R_SUCCESS) - goto cleanup_algorithm; + goto cleanup_other; /* * If this is a response, digest the query signature. */ if (is_response(msg)) { - isc_buffer_putuint16(&databuf, msg->querytsig->siglen); - isc_buffer_availableregion(&databuf, &r); - if (r.length < msg->querytsig->siglen) - return (ISC_R_NOSPACE); - memcpy(r.base, msg->querytsig->signature, - msg->querytsig->siglen); - isc_buffer_add(&databuf, msg->querytsig->siglen); + dns_rdata_t querytsigrdata; + + ret = dns_rdataset_first(msg->querytsig); + if (ret != ISC_R_SUCCESS) + goto cleanup_context; + dns_rdataset_current(msg->querytsig, &querytsigrdata); + ret = dns_rdata_tostruct(&querytsigrdata, &querytsig, + NULL); + if (ret != ISC_R_SUCCESS) + goto cleanup_context; + isc_buffer_putuint16(&databuf, querytsig.siglen); + if (isc_buffer_availablelength(&databuf) < + querytsig.siglen) + { + ret = ISC_R_NOSPACE; + goto cleanup_context; + } + isc_buffer_putmem(&databuf, querytsig.signature, + querytsig.siglen); isc_buffer_usedregion(&databuf, &r); - ret = dst_key_sign(DST_SIGMODE_UPDATE, key->key, &ctx, - &r, NULL); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_algorithm; + goto cleanup_context; } /* @@ -347,45 +352,40 @@ dns_tsig_sign(dns_message_t *msg) { isc_buffer_init(&headerbuf, header, sizeof(header)); dns_message_renderheader(msg, &headerbuf); isc_buffer_usedregion(&headerbuf, &r); - ret = dst_key_sign(DST_SIGMODE_UPDATE, key->key, &ctx, &r, - NULL); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_other; + goto cleanup_context; /* * Digest the remainder of the message. */ isc_buffer_usedregion(msg->buffer, &r); isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); - ret = dst_key_sign(DST_SIGMODE_UPDATE, key->key, &ctx, &r, - NULL); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_other; + goto cleanup_context; if (msg->tcp_continuation == 0) { /* * Digest the name, class, ttl, alg. */ dns_name_toregion(&key->name, &r); - ret = dst_key_sign(DST_SIGMODE_UPDATE, key->key, &ctx, - &r, NULL); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_other; + goto cleanup_context; isc_buffer_clear(&databuf); isc_buffer_putuint16(&databuf, dns_rdataclass_any); isc_buffer_putuint32(&databuf, 0); /* ttl */ isc_buffer_usedregion(&databuf, &r); - ret = dst_key_sign(DST_SIGMODE_UPDATE, key->key, &ctx, - &r, NULL); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_other; + goto cleanup_context; dns_name_toregion(&tsig.algorithm, &r); - ret = dst_key_sign(DST_SIGMODE_UPDATE, key->key, &ctx, - &r, NULL); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_other; + goto cleanup_context; } /* Digest the timesigned and fudge */ @@ -399,7 +399,7 @@ dns_tsig_sign(dns_message_t *msg) { 0xFFFFFFFF)); } else { - isc_uint64_t querysigned = msg->querytsig->timesigned; + isc_uint64_t querysigned = querytsig.timesigned; isc_buffer_putuint16(&databuf, (isc_uint16_t)(querysigned >> 32)); @@ -409,10 +409,9 @@ dns_tsig_sign(dns_message_t *msg) { } isc_buffer_putuint16(&databuf, tsig.fudge); isc_buffer_usedregion(&databuf, &r); - ret = dst_key_sign(DST_SIGMODE_UPDATE, key->key, &ctx, &r, - NULL); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_other; + goto cleanup_context; if (msg->tcp_continuation == 0) { /* @@ -423,10 +422,9 @@ dns_tsig_sign(dns_message_t *msg) { isc_buffer_putuint16(&databuf, tsig.otherlen); isc_buffer_usedregion(&databuf, &r); - ret = dst_key_sign(DST_SIGMODE_UPDATE, key->key, &ctx, - &r, NULL); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_other; + goto cleanup_context; /* * Digest the error and other data. @@ -434,29 +432,28 @@ dns_tsig_sign(dns_message_t *msg) { if (tsig.otherlen > 0) { r.length = tsig.otherlen; r.base = tsig.other; - ret = dst_key_sign(DST_SIGMODE_UPDATE, key->key, - &ctx, &r, NULL); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_other; + goto cleanup_context; } } ret = dst_key_sigsize(key->key, &sigsize); if (ret != ISC_R_SUCCESS) - goto cleanup_other; + goto cleanup_context; tsig.siglen = sigsize; tsig.signature = (unsigned char *) isc_mem_get(mctx, tsig.siglen); if (tsig.signature == NULL) { ret = ISC_R_NOMEMORY; - goto cleanup_other; + goto cleanup_context; } isc_buffer_init(&sigbuf, tsig.signature, tsig.siglen); - ret = dst_key_sign(DST_SIGMODE_FINAL, key->key, &ctx, NULL, - &sigbuf); + ret = dst_context_sign(ctx, &sigbuf); if (ret != ISC_R_SUCCESS) goto cleanup_signature; + dst_context_destroy(&ctx); } else { tsig.siglen = 0; @@ -475,6 +472,8 @@ dns_tsig_sign(dns_message_t *msg) { if (ret != ISC_R_SUCCESS) goto cleanup_dynbuf; + dns_message_takebuffer(msg, &dynbuf); + if (tsig.signature != NULL) { isc_mem_put(mctx, tsig.signature, tsig.siglen); tsig.signature = NULL; @@ -483,29 +482,16 @@ dns_tsig_sign(dns_message_t *msg) { isc_mem_put(mctx, tsig.other, tsig.otherlen); tsig.other = NULL; } - dns_name_free(&tsig.algorithm, mctx); - algfreed = ISC_TRUE; - - msg->tsig = isc_mem_get(mctx, sizeof(dns_rdata_any_tsig_t)); - if (msg->tsig == NULL) { - ret = ISC_R_NOMEMORY; - goto cleanup_dynbuf; - } - ret = dns_rdata_tostruct(rdata, msg->tsig, mctx); - if (ret != ISC_R_SUCCESS) - goto cleanup_tsig; - - dns_message_takebuffer(msg, &dynbuf); owner = NULL; ret = dns_message_gettempname(msg, &owner); if (ret != ISC_R_SUCCESS) - goto cleanup_tsig; + goto cleanup_dynbuf; dns_name_toregion(&key->name, &r); dynbuf = NULL; ret = isc_buffer_allocate(mctx, &dynbuf, r.length); if (ret != ISC_R_SUCCESS) - goto cleanup_tsig; + goto cleanup_dynbuf; isc_buffer_availableregion(dynbuf, &r2); memcpy(r2.base, r.base, r.length); dns_name_init(owner, NULL); @@ -515,7 +501,7 @@ dns_tsig_sign(dns_message_t *msg) { datalist = NULL; ret = dns_message_gettemprdatalist(msg, &datalist); if (ret != ISC_R_SUCCESS) - goto cleanup_tsig; + goto cleanup_dynbuf; datalist->rdclass = dns_rdataclass_any; datalist->type = dns_rdatatype_tsig; datalist->covers = 0; @@ -525,31 +511,26 @@ dns_tsig_sign(dns_message_t *msg) { dataset = NULL; ret = dns_message_gettemprdataset(msg, &dataset); if (ret != ISC_R_SUCCESS) - goto cleanup_tsig; + goto cleanup_dynbuf; dns_rdataset_init(dataset); dns_rdatalist_tordataset(datalist, dataset); - msg->tsigset = dataset; + msg->tsig = dataset; msg->tsigname = owner; return (ISC_R_SUCCESS); -cleanup_tsig: - dns_rdata_freestruct(msg->tsig); - isc_mem_put(mctx, msg->tsig, sizeof *msg->tsig); cleanup_dynbuf: if (dynbuf != NULL) isc_buffer_free(&dynbuf); cleanup_signature: if (tsig.signature != NULL) isc_mem_put(mctx, tsig.signature, tsig.siglen); +cleanup_context: + if (ctx != NULL) + dst_context_destroy(&ctx); cleanup_other: if (tsig.other != NULL) isc_mem_put(mctx, tsig.other, tsig.otherlen); -cleanup_algorithm: - if (!algfreed) - dns_name_free(&tsig.algorithm, mctx); -cleanup_struct: - msg->tsig = NULL; return (ret); } @@ -558,7 +539,7 @@ isc_result_t dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, dns_tsig_keyring_t *sring, dns_tsig_keyring_t *dring) { - dns_rdata_any_tsig_t *tsig; + dns_rdata_any_tsig_t tsig, querytsig; isc_region_t r, source_r, header_r, sig_r; isc_buffer_t databuf; unsigned char data[32]; @@ -566,18 +547,17 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, dns_rdata_t rdata; isc_stdtime_t now; isc_result_t ret; - dns_tsigkey_t *tsigkey = NULL; + dns_tsigkey_t *tsigkey; dst_key_t *key = NULL; unsigned char header[DNS_MESSAGE_HEADERLEN]; - dst_context_t ctx; + dst_context_t *ctx = NULL; isc_mem_t *mctx; isc_uint16_t addcount, id; REQUIRE(source != NULL); REQUIRE(DNS_MESSAGE_VALID(msg)); - REQUIRE(msg->tsig == NULL); - if (msg->tsigkey != NULL) - REQUIRE(VALID_TSIG_KEY(msg->tsigkey)); + tsigkey = dns_message_gettsigkey(msg); + REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey)); msg->verify_attempted = 1; @@ -587,7 +567,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, /* * There should be a TSIG record... */ - if (msg->tsigset == NULL) + if (msg->tsig == NULL) return (DNS_R_EXPECTEDTSIG); /* @@ -595,7 +575,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, * shouldn't be one on the response. */ if (is_response(msg) && - (msg->tsigkey == NULL || msg->querytsig == NULL)) + (tsigkey == NULL || msg->querytsig == NULL)) return (DNS_R_UNEXPECTEDTSIG); mctx = msg->mctx; @@ -606,25 +586,29 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, */ keyname = msg->tsigname; - ret = dns_rdataset_first(msg->tsigset); + ret = dns_rdataset_first(msg->tsig); if (ret != ISC_R_SUCCESS) return (ret); - dns_rdataset_current(msg->tsigset, &rdata); - tsig = (dns_rdata_any_tsig_t *) - isc_mem_get(mctx, sizeof(dns_rdata_any_tsig_t)); - if (tsig == NULL) - return (ISC_R_NOMEMORY); - msg->tsig = tsig; - ret = dns_rdata_tostruct(&rdata, tsig, mctx); + dns_rdataset_current(msg->tsig, &rdata); + ret = dns_rdata_tostruct(&rdata, &tsig, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_emptystruct; + return (ret); + if (is_response(msg)) { + ret = dns_rdataset_first(msg->querytsig); + if (ret != ISC_R_SUCCESS) + return (ret); + dns_rdataset_current(msg->querytsig, &rdata); + ret = dns_rdata_tostruct(&rdata, &querytsig, NULL); + if (ret != ISC_R_SUCCESS) + return (ret); + } /* * Do the key name and algorithm match that of the query? */ if (is_response(msg) && - (!dns_name_equal(keyname, &msg->tsigkey->name) || - !dns_name_equal(&tsig->algorithm, &msg->querytsig->algorithm))) + (!dns_name_equal(keyname, &tsigkey->name) || + !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) { msg->tsigstatus = dns_tsigerror_badkey; return (DNS_R_TSIGVERIFYFAILURE); @@ -638,67 +622,60 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, /* * Find dns_tsigkey_t based on keyname. */ - if (msg->tsigkey == NULL) { + if (tsigkey == NULL) { ret = ISC_R_NOTFOUND; if (sring != NULL) ret = dns_tsigkey_find(&tsigkey, keyname, - &tsig->algorithm, sring); + &tsig.algorithm, sring); if (ret == ISC_R_NOTFOUND && dring != NULL) ret = dns_tsigkey_find(&tsigkey, keyname, - &tsig->algorithm, dring); + &tsig.algorithm, dring); if (ret != ISC_R_SUCCESS) { - if (dring == NULL) { - ret = DNS_R_TSIGVERIFYFAILURE; - goto cleanup_struct; - } + if (dring == NULL) + return (DNS_R_TSIGVERIFYFAILURE); msg->tsigstatus = dns_tsigerror_badkey; - msg->tsigkey = NULL; - ret = dns_tsigkey_create(keyname, &tsig->algorithm, + ret = dns_tsigkey_create(keyname, &tsig.algorithm, NULL, 0, ISC_FALSE, NULL, now, now, mctx, dring, &msg->tsigkey); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + return (ret); return (DNS_R_TSIGVERIFYFAILURE); } msg->tsigkey = tsigkey; } - else - tsigkey = msg->tsigkey; key = tsigkey->key; /* * Is the time ok? */ - if (abs(now - tsig->timesigned) > tsig->fudge) { + if (abs(now - tsig.timesigned) > tsig.fudge) { msg->tsigstatus = dns_tsigerror_badtime; return (DNS_R_TSIGVERIFYFAILURE); } - if (tsig->siglen > 0) { - sig_r.base = tsig->signature; - sig_r.length = tsig->siglen; + if (tsig.siglen > 0) { + sig_r.base = tsig.signature; + sig_r.length = tsig.siglen; - ret = dst_key_verify(DST_SIGMODE_INIT, key, &ctx, NULL, &sig_r); + ret = dst_context_create(key, mctx, &ctx); if (ret != ISC_R_SUCCESS) goto cleanup_key; if (is_response(msg)) { isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, msg->querytsig->siglen); + isc_buffer_putuint16(&databuf, querytsig.siglen); isc_buffer_usedregion(&databuf, &r); - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, - NULL); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_key; - if (msg->querytsig->siglen > 0) { - r.length = msg->querytsig->siglen; - r.base = msg->querytsig->signature; - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, - &ctx, &r, NULL); + goto cleanup_context; + if (querytsig.siglen > 0) { + r.length = querytsig.siglen; + r.base = querytsig.signature; + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_key; + goto cleanup_context; } } @@ -719,7 +696,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, /* * Put in the original id. */ - id = htons(tsig->originalid); + id = htons(tsig.originalid); memcpy(&header[0], &id, 2); /* @@ -727,10 +704,9 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, */ header_r.base = (unsigned char *) header; header_r.length = DNS_MESSAGE_HEADERLEN; - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &header_r, - &sig_r); + ret = dst_context_adddata(ctx, &header_r); if (ret != ISC_R_SUCCESS) - goto cleanup_key; + goto cleanup_context; /* * Digest all non-TSIG records. @@ -738,65 +714,68 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, isc_buffer_usedregion(source, &source_r); r.base = source_r.base + DNS_MESSAGE_HEADERLEN; r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, &sig_r); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_key; + goto cleanup_context; /* * Digest the key name. */ dns_name_toregion(&tsigkey->name, &r); - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, &sig_r); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_key; + goto cleanup_context; isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, tsig->common.rdclass); - isc_buffer_putuint32(&databuf, msg->tsigset->ttl); + isc_buffer_putuint16(&databuf, tsig.common.rdclass); + isc_buffer_putuint32(&databuf, msg->tsig->ttl); isc_buffer_usedregion(&databuf, &r); - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, &sig_r); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_key; + goto cleanup_context; /* * Digest the key algorithm. */ dns_name_toregion(&tsigkey->algorithm, &r); - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, &sig_r); + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_key; + goto cleanup_context; isc_buffer_clear(&databuf); - isc_buffer_putuint16(&databuf, (isc_uint16_t)(tsig->timesigned + isc_buffer_putuint16(&databuf, (isc_uint16_t)(tsig.timesigned >> 32)); - isc_buffer_putuint32(&databuf, (isc_uint32_t)(tsig->timesigned + isc_buffer_putuint32(&databuf, (isc_uint32_t)(tsig.timesigned & 0xFFFFFFFF)); - isc_buffer_putuint16(&databuf, tsig->fudge); - isc_buffer_putuint16(&databuf, tsig->error); - isc_buffer_putuint16(&databuf, tsig->otherlen); + isc_buffer_putuint16(&databuf, tsig.fudge); + isc_buffer_putuint16(&databuf, tsig.error); + isc_buffer_putuint16(&databuf, tsig.otherlen); isc_buffer_usedregion(&databuf, &r); - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, &sig_r); + ret = dst_context_adddata(ctx, &r); + if (ret != ISC_R_SUCCESS) + goto cleanup_context; - if (tsig->otherlen > 0) { - r.base = tsig->other; - r.length = tsig->otherlen; - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &ctx, &r, - &sig_r); + if (tsig.otherlen > 0) { + r.base = tsig.other; + r.length = tsig.otherlen; + ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_key; + goto cleanup_context; } - ret = dst_key_verify(DST_SIGMODE_FINAL, key, &ctx, NULL, - &sig_r); - if (ret == DST_R_VERIFYFINALFAILURE) { + ret = dst_context_verify(ctx, &sig_r); + if (ret == DST_R_VERIFYFAILURE) { msg->tsigstatus = dns_tsigerror_badsig; - return (DNS_R_TSIGVERIFYFAILURE); + ret = DNS_R_TSIGVERIFYFAILURE; + goto cleanup_context; } else if (ret != ISC_R_SUCCESS) - goto cleanup_key; + goto cleanup_context; + + dst_context_destroy(&ctx); } - else if (tsig->error != dns_tsigerror_badsig && - tsig->error != dns_tsigerror_badkey) + else if (tsig.error != dns_tsigerror_badsig && + tsig.error != dns_tsigerror_badkey) { msg->tsigstatus = dns_tsigerror_badsig; return (DNS_R_TSIGVERIFYFAILURE); @@ -804,7 +783,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, msg->tsigstatus = dns_rcode_noerror; - if (tsig->error != dns_rcode_noerror) { + if (tsig.error != dns_rcode_noerror) { if (is_response(msg)) { /* XXXBEW Log a message */ return (ISC_R_SUCCESS); @@ -817,22 +796,19 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, return (ISC_R_SUCCESS); +cleanup_context: + if (ctx != NULL) + dst_context_destroy(&ctx); cleanup_key: - if (dns_tsigkey_empty(msg->tsigkey)) { - dns_tsigkey_free(&msg->tsigkey); - msg->tsigkey = NULL; - } -cleanup_struct: - dns_rdata_freestruct(tsig); -cleanup_emptystruct: - msg->tsig = NULL; - isc_mem_put(mctx, tsig, sizeof(dns_rdata_any_tsig_t)); + if (dns_tsigkey_empty(tsigkey)) + dns_tsigkey_detach(&tsigkey); + return (ret); } static isc_result_t dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - dns_rdata_any_tsig_t *tsig = NULL; + dns_rdata_any_tsig_t tsig, querytsig; isc_region_t r, source_r, header_r, sig_r; isc_buffer_t databuf; unsigned char data[32]; @@ -840,45 +816,48 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { dns_rdata_t rdata; isc_stdtime_t now; isc_result_t ret; + dns_tsigkey_t *tsigkey; dst_key_t *key = NULL; unsigned char header[DNS_MESSAGE_HEADERLEN]; - isc_mem_t *mctx; isc_uint16_t addcount, id; isc_boolean_t has_tsig = ISC_FALSE; + isc_mem_t *mctx; REQUIRE(source != NULL); REQUIRE(msg != NULL); - REQUIRE(msg->tsig == NULL); - REQUIRE(msg->tsigkey != NULL); + REQUIRE(dns_message_gettsigkey(msg) != NULL); REQUIRE(msg->tcp_continuation == 1); REQUIRE(is_response(msg)); REQUIRE(msg->querytsig != NULL); mctx = msg->mctx; - if (msg->tsigset != NULL) { + tsigkey = dns_message_gettsigkey(msg); + + if (msg->tsig != NULL) { has_tsig = ISC_TRUE; keyname = msg->tsigname; - ret = dns_rdataset_first(msg->tsigset); + ret = dns_rdataset_first(msg->tsig); if (ret != ISC_R_SUCCESS) return (ret); - dns_rdataset_current(msg->tsigset, &rdata); - tsig = (dns_rdata_any_tsig_t *) - isc_mem_get(mctx, sizeof(dns_rdata_any_tsig_t)); - if (tsig == NULL) - return (ISC_R_NOMEMORY); - msg->tsig = tsig; - ret = dns_rdata_tostruct(&rdata, tsig, mctx); + dns_rdataset_current(msg->tsig, &rdata); + ret = dns_rdata_tostruct(&rdata, &tsig, NULL); if (ret != ISC_R_SUCCESS) - goto cleanup_emptystruct; + return (ret); + ret = dns_rdataset_first(msg->querytsig); + if (ret != ISC_R_SUCCESS) + return (ret); + dns_rdataset_current(msg->querytsig, &rdata); + ret = dns_rdata_tostruct(&rdata, &querytsig, NULL); + if (ret != ISC_R_SUCCESS) + return (ret); /* * Do the key name and algorithm match that of the query? */ - if (!dns_name_equal(keyname, &msg->tsigkey->name) || - !dns_name_equal(&tsig->algorithm, - &msg->querytsig->algorithm)) + if (!dns_name_equal(keyname, &tsigkey->name) || + !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) { msg->tsigstatus = dns_tsigerror_badkey; return (DNS_R_TSIGVERIFYFAILURE); @@ -888,34 +867,31 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { * Is the time ok? */ isc_stdtime_get(&now); - if (abs(now - tsig->timesigned) > tsig->fudge) { + if (abs(now - tsig.timesigned) > tsig.fudge) { msg->tsigstatus = dns_tsigerror_badtime; return (DNS_R_TSIGVERIFYFAILURE); } } - key = msg->tsigkey->key; + key = tsigkey->key; if (msg->tsigctx == NULL) { - ret = dst_key_verify(DST_SIGMODE_INIT, key, &msg->tsigctx, - NULL, NULL); + ret = dst_context_create(key, mctx, &msg->tsigctx); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + return (ret); isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, msg->querytsig->siglen); + isc_buffer_putuint16(&databuf, querytsig.siglen); isc_buffer_usedregion(&databuf, &r); - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &msg->tsigctx, - &r, NULL); + ret = dst_context_adddata(msg->tsigctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; - if (msg->querytsig->siglen > 0) { - r.length = msg->querytsig->siglen; - r.base = msg->querytsig->signature; - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, - &msg->tsigctx, &r, NULL); + goto cleanup_context; + if (querytsig.siglen > 0) { + r.length = querytsig.siglen; + r.base = querytsig.signature; + ret = dst_context_adddata(msg->tsigctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + goto cleanup_context; } } @@ -939,8 +915,8 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { * Put in the original id. */ /* XXX Can TCP transfers be forwarded? How would that work? */ - if (tsig != NULL) { - id = htons(tsig->originalid); + if (has_tsig) { + id = htons(tsig.originalid); memcpy(&header[0], &id, 2); } @@ -949,10 +925,9 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { */ header_r.base = (unsigned char *) header; header_r.length = DNS_MESSAGE_HEADERLEN; - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &msg->tsigctx, &header_r, - NULL); + ret = dst_context_adddata(msg->tsigctx, &header_r); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + goto cleanup_context; /* * Digest all non-TSIG records. @@ -963,55 +938,54 @@ dns_tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; else r.length = source_r.length - DNS_MESSAGE_HEADERLEN; - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &msg->tsigctx, &r, NULL); + ret = dst_context_adddata(msg->tsigctx, &r); if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + goto cleanup_context; /* * Digest the time signed and fudge. */ if (has_tsig) { isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, (isc_uint16_t)(tsig->timesigned + isc_buffer_putuint16(&databuf, (isc_uint16_t)(tsig.timesigned >> 32)); - isc_buffer_putuint32(&databuf, (isc_uint32_t)(tsig->timesigned + isc_buffer_putuint32(&databuf, (isc_uint32_t)(tsig.timesigned & 0xFFFFFFFF)); - isc_buffer_putuint16(&databuf, tsig->fudge); + isc_buffer_putuint16(&databuf, tsig.fudge); isc_buffer_usedregion(&databuf, &r); - ret = dst_key_verify(DST_SIGMODE_UPDATE, key, &msg->tsigctx, &r, - NULL); + ret = dst_context_adddata(msg->tsigctx, &r); + if (ret != ISC_R_SUCCESS) + goto cleanup_context; - sig_r.base = tsig->signature; - sig_r.length = tsig->siglen; - if (tsig->siglen == 0) { - if (tsig->error != dns_rcode_noerror) + sig_r.base = tsig.signature; + sig_r.length = tsig.siglen; + if (tsig.siglen == 0) { + if (tsig.error != dns_rcode_noerror) ret = DNS_R_TSIGERRORSET; else ret = DNS_R_TSIGVERIFYFAILURE; - goto cleanup_struct; + goto cleanup_context; } - ret = dst_key_verify(DST_SIGMODE_FINAL, key, &msg->tsigctx, - NULL, &sig_r); - if (ret == DST_R_VERIFYFINALFAILURE) { + ret = dst_context_verify(msg->tsigctx, &sig_r); + if (ret == DST_R_VERIFYFAILURE) { msg->tsigstatus = dns_tsigerror_badsig; - return (DNS_R_TSIGVERIFYFAILURE); + ret = DNS_R_TSIGVERIFYFAILURE; + goto cleanup_context; } else if (ret != ISC_R_SUCCESS) - goto cleanup_struct; + goto cleanup_context; - msg->tsigctx = NULL; + dst_context_destroy(&msg->tsigctx); } msg->tsigstatus = dns_rcode_noerror; return (ISC_R_SUCCESS); -cleanup_struct: - dns_rdata_freestruct(tsig); -cleanup_emptystruct: - msg->tsig = NULL; - isc_mem_put(mctx, tsig, sizeof(dns_rdata_any_tsig_t)); + cleanup_context: + dst_context_destroy(&msg->tsigctx); return (ret); + } isc_result_t @@ -1059,19 +1033,19 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name, } static void -dns_tsig_inithmac() { - isc_region_t r; - char *str = "\010HMAC-MD5\007SIG-ALG\003REG\003INT"; +dns_tsig_inithmac(void) { + isc_constregion_t r; + const char *str = "\010HMAC-MD5\007SIG-ALG\003REG\003INT"; + dns_name_init(&hmacmd5_name, NULL); - r.base = (unsigned char *)str; + r.base = str; r.length = strlen(str) + 1; - dns_name_fromregion(&hmacmd5_name, &r); + dns_name_fromregion(&hmacmd5_name, (isc_region_t *)&r); dns_tsig_hmacmd5_name = &hmacmd5_name; } isc_result_t -dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ring) -{ +dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ring) { isc_result_t ret; REQUIRE(mctx != NULL); @@ -1109,7 +1083,7 @@ dns_tsigkeyring_destroy(dns_tsig_keyring_t **ring) { dns_tsigkey_t *key = ISC_LIST_HEAD((*ring)->keys); key->refs = 0; key->deleted = ISC_TRUE; - tsigkey_free(&key); + tsigkey_free(key); } isc_rwlock_destroy(&(*ring)->lock); mctx = (*ring)->mctx; |