diff options
Diffstat (limited to 'contrib/bind9/lib/dns/tsig.c')
-rw-r--r-- | contrib/bind9/lib/dns/tsig.c | 1464 |
1 files changed, 0 insertions, 1464 deletions
diff --git a/contrib/bind9/lib/dns/tsig.c b/contrib/bind9/lib/dns/tsig.c deleted file mode 100644 index cca1f99..0000000 --- a/contrib/bind9/lib/dns/tsig.c +++ /dev/null @@ -1,1464 +0,0 @@ -/* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2002 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * $Id: tsig.c,v 1.117.18.11 2007/09/26 23:46:34 tbox Exp $ - */ -/*! \file */ -#include <config.h> -#include <stdlib.h> - -#include <isc/buffer.h> -#include <isc/mem.h> -#include <isc/print.h> -#include <isc/refcount.h> -#include <isc/string.h> /* Required for HP/UX (and others?) */ -#include <isc/util.h> - -#include <dns/keyvalues.h> -#include <dns/log.h> -#include <dns/message.h> -#include <dns/rbt.h> -#include <dns/rdata.h> -#include <dns/rdatalist.h> -#include <dns/rdataset.h> -#include <dns/rdatastruct.h> -#include <dns/result.h> -#include <dns/tsig.h> - -#include <dst/result.h> - -#define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G') -#define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC) - -#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR) -#define algname_is_allocated(algname) \ - ((algname) != dns_tsig_hmacmd5_name && \ - (algname) != dns_tsig_hmacsha1_name && \ - (algname) != dns_tsig_hmacsha224_name && \ - (algname) != dns_tsig_hmacsha256_name && \ - (algname) != dns_tsig_hmacsha384_name && \ - (algname) != dns_tsig_hmacsha512_name && \ - (algname) != dns_tsig_gssapi_name && \ - (algname) != dns_tsig_gssapims_name) - -#define BADTIMELEN 6 - -static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int"; -static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 }; - -static dns_name_t hmacmd5 = { - DNS_NAME_MAGIC, - hmacmd5_ndata, 26, 5, - DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, - hmacmd5_offsets, NULL, - {(void *)-1, (void *)-1}, - {NULL, NULL} -}; - -dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5; - -static unsigned char gsstsig_ndata[] = "\010gss-tsig"; -static unsigned char gsstsig_offsets[] = { 0, 9 }; - -static dns_name_t gsstsig = { - DNS_NAME_MAGIC, - gsstsig_ndata, 10, 2, - DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, - gsstsig_offsets, NULL, - {(void *)-1, (void *)-1}, - {NULL, NULL} -}; - -LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig; - -/* It's nice of Microsoft to conform to their own standard. */ -static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com"; -static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 }; - -static dns_name_t gsstsigms = { - DNS_NAME_MAGIC, - gsstsigms_ndata, 19, 4, - DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, - gsstsigms_offsets, NULL, - {(void *)-1, (void *)-1}, - {NULL, NULL} -}; - -LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms; - -static unsigned char hmacsha1_ndata[] = "\011hmac-sha1"; -static unsigned char hmacsha1_offsets[] = { 0, 10 }; - -static dns_name_t hmacsha1 = { - DNS_NAME_MAGIC, - hmacsha1_ndata, 11, 2, - DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, - hmacsha1_offsets, NULL, - {(void *)-1, (void *)-1}, - {NULL, NULL} -}; - -LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1; - -static unsigned char hmacsha224_ndata[] = "\013hmac-sha224"; -static unsigned char hmacsha224_offsets[] = { 0, 12 }; - -static dns_name_t hmacsha224 = { - DNS_NAME_MAGIC, - hmacsha224_ndata, 13, 2, - DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, - hmacsha224_offsets, NULL, - {(void *)-1, (void *)-1}, - {NULL, NULL} -}; - -LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224; - -static unsigned char hmacsha256_ndata[] = "\013hmac-sha256"; -static unsigned char hmacsha256_offsets[] = { 0, 12 }; - -static dns_name_t hmacsha256 = { - DNS_NAME_MAGIC, - hmacsha256_ndata, 13, 2, - DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, - hmacsha256_offsets, NULL, - {(void *)-1, (void *)-1}, - {NULL, NULL} -}; - -LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256; - -static unsigned char hmacsha384_ndata[] = "\013hmac-sha384"; -static unsigned char hmacsha384_offsets[] = { 0, 12 }; - -static dns_name_t hmacsha384 = { - DNS_NAME_MAGIC, - hmacsha384_ndata, 13, 2, - DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, - hmacsha384_offsets, NULL, - {(void *)-1, (void *)-1}, - {NULL, NULL} -}; - -LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384; - -static unsigned char hmacsha512_ndata[] = "\013hmac-sha512"; -static unsigned char hmacsha512_offsets[] = { 0, 12 }; - -static dns_name_t hmacsha512 = { - DNS_NAME_MAGIC, - hmacsha512_ndata, 13, 2, - DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, - hmacsha512_offsets, NULL, - {(void *)-1, (void *)-1}, - {NULL, NULL} -}; - -LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512; - -static isc_result_t -tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg); - -static void -tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) - ISC_FORMAT_PRINTF(3, 4); - -static void -tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) { - va_list ap; - char message[4096]; - char namestr[DNS_NAME_FORMATSIZE]; - - if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) - return; - if (key != NULL) - dns_name_format(&key->name, namestr, sizeof(namestr)); - else - strcpy(namestr, "<null>"); - va_start(ap, fmt); - vsnprintf(message, sizeof(message), fmt, ap); - va_end(ap); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG, - level, "tsig key '%s': %s", namestr, message); -} - -isc_result_t -dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, - dst_key_t *dstkey, isc_boolean_t generated, - dns_name_t *creator, isc_stdtime_t inception, - isc_stdtime_t expire, isc_mem_t *mctx, - dns_tsig_keyring_t *ring, dns_tsigkey_t **key) -{ - dns_tsigkey_t *tkey; - isc_result_t ret; - unsigned int refs = 0; - - REQUIRE(key == NULL || *key == NULL); - REQUIRE(name != NULL); - REQUIRE(algorithm != NULL); - REQUIRE(mctx != NULL); - REQUIRE(key != NULL || ring != NULL); - - tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t)); - if (tkey == NULL) - return (ISC_R_NOMEMORY); - - dns_name_init(&tkey->name, NULL); - ret = dns_name_dup(name, mctx, &tkey->name); - if (ret != ISC_R_SUCCESS) - goto cleanup_key; - (void)dns_name_downcase(&tkey->name, &tkey->name, NULL); - - if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { - tkey->algorithm = DNS_TSIG_HMACMD5_NAME; - if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) { - ret = DNS_R_BADALG; - goto cleanup_name; - } - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { - tkey->algorithm = DNS_TSIG_HMACSHA1_NAME; - if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) { - ret = DNS_R_BADALG; - goto cleanup_name; - } - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) { - tkey->algorithm = DNS_TSIG_HMACSHA224_NAME; - if (dstkey != NULL && - dst_key_alg(dstkey) != DST_ALG_HMACSHA224) { - ret = DNS_R_BADALG; - goto cleanup_name; - } - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) { - tkey->algorithm = DNS_TSIG_HMACSHA256_NAME; - if (dstkey != NULL && - dst_key_alg(dstkey) != DST_ALG_HMACSHA256) { - ret = DNS_R_BADALG; - goto cleanup_name; - } - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) { - tkey->algorithm = DNS_TSIG_HMACSHA384_NAME; - if (dstkey != NULL && - dst_key_alg(dstkey) != DST_ALG_HMACSHA384) { - ret = DNS_R_BADALG; - goto cleanup_name; - } - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) { - tkey->algorithm = DNS_TSIG_HMACSHA512_NAME; - if (dstkey != NULL && - dst_key_alg(dstkey) != DST_ALG_HMACSHA512) { - ret = DNS_R_BADALG; - goto cleanup_name; - } - } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) { - tkey->algorithm = DNS_TSIG_GSSAPI_NAME; - if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) { - ret = DNS_R_BADALG; - goto cleanup_name; - } - } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) { - tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME; - if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) { - ret = DNS_R_BADALG; - goto cleanup_name; - } - } else { - if (dstkey != NULL) { - ret = DNS_R_BADALG; - goto cleanup_name; - } - tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t)); - if (tkey->algorithm == NULL) { - ret = ISC_R_NOMEMORY; - goto cleanup_name; - } - dns_name_init(tkey->algorithm, NULL); - ret = dns_name_dup(algorithm, mctx, tkey->algorithm); - if (ret != ISC_R_SUCCESS) - goto cleanup_algorithm; - (void)dns_name_downcase(tkey->algorithm, tkey->algorithm, - NULL); - } - - if (creator != NULL) { - tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t)); - if (tkey->creator == NULL) { - ret = ISC_R_NOMEMORY; - goto cleanup_algorithm; - } - dns_name_init(tkey->creator, NULL); - ret = dns_name_dup(creator, mctx, tkey->creator); - if (ret != ISC_R_SUCCESS) { - isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t)); - goto cleanup_algorithm; - } - } else - tkey->creator = NULL; - - tkey->key = dstkey; - tkey->ring = ring; - - if (key != NULL) - refs++; - if (ring != NULL) - refs++; - ret = isc_refcount_init(&tkey->refs, refs); - if (ret != ISC_R_SUCCESS) - goto cleanup_creator; - - tkey->generated = generated; - tkey->inception = inception; - tkey->expire = expire; - tkey->mctx = mctx; - - tkey->magic = TSIG_MAGIC; - - if (ring != NULL) { - RWLOCK(&ring->lock, isc_rwlocktype_write); - ret = dns_rbt_addname(ring->keys, name, tkey); - if (ret != ISC_R_SUCCESS) { - RWUNLOCK(&ring->lock, isc_rwlocktype_write); - goto cleanup_refs; - } - RWUNLOCK(&ring->lock, isc_rwlocktype_write); - } - - if (dstkey != NULL && dst_key_size(dstkey) < 64) { - char namestr[DNS_NAME_FORMATSIZE]; - dns_name_format(name, namestr, sizeof(namestr)); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, - DNS_LOGMODULE_TSIG, ISC_LOG_INFO, - "the key '%s' is too short to be secure", - namestr); - } - if (key != NULL) - *key = tkey; - - return (ISC_R_SUCCESS); - - cleanup_refs: - tkey->magic = 0; - while (refs-- > 0) - isc_refcount_decrement(&tkey->refs, NULL); - isc_refcount_destroy(&tkey->refs); - cleanup_creator: - if (tkey->creator != NULL) { - dns_name_free(tkey->creator, mctx); - isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t)); - } - cleanup_algorithm: - if (algname_is_allocated(tkey->algorithm)) { - if (dns_name_dynamic(tkey->algorithm)) - dns_name_free(tkey->algorithm, mctx); - isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t)); - } - cleanup_name: - dns_name_free(&tkey->name, mctx); - cleanup_key: - isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t)); - - return (ret); -} - -isc_result_t -dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm, - unsigned char *secret, int length, isc_boolean_t generated, - dns_name_t *creator, isc_stdtime_t inception, - isc_stdtime_t expire, isc_mem_t *mctx, - dns_tsig_keyring_t *ring, dns_tsigkey_t **key) -{ - dst_key_t *dstkey = NULL; - isc_result_t result; - - REQUIRE(length >= 0); - if (length > 0) - REQUIRE(secret != NULL); - - if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { - if (secret != NULL) { - isc_buffer_t b; - - isc_buffer_init(&b, secret, length); - isc_buffer_add(&b, length); - result = dst_key_frombuffer(name, DST_ALG_HMACMD5, - DNS_KEYOWNER_ENTITY, - DNS_KEYPROTO_DNSSEC, - dns_rdataclass_in, - &b, mctx, &dstkey); - if (result != ISC_R_SUCCESS) - return (result); - } - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { - if (secret != NULL) { - isc_buffer_t b; - - isc_buffer_init(&b, secret, length); - isc_buffer_add(&b, length); - result = dst_key_frombuffer(name, DST_ALG_HMACSHA1, - DNS_KEYOWNER_ENTITY, - DNS_KEYPROTO_DNSSEC, - dns_rdataclass_in, - &b, mctx, &dstkey); - if (result != ISC_R_SUCCESS) - return (result); - } - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) { - if (secret != NULL) { - isc_buffer_t b; - - isc_buffer_init(&b, secret, length); - isc_buffer_add(&b, length); - result = dst_key_frombuffer(name, DST_ALG_HMACSHA224, - DNS_KEYOWNER_ENTITY, - DNS_KEYPROTO_DNSSEC, - dns_rdataclass_in, - &b, mctx, &dstkey); - if (result != ISC_R_SUCCESS) - return (result); - } - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) { - if (secret != NULL) { - isc_buffer_t b; - - isc_buffer_init(&b, secret, length); - isc_buffer_add(&b, length); - result = dst_key_frombuffer(name, DST_ALG_HMACSHA256, - DNS_KEYOWNER_ENTITY, - DNS_KEYPROTO_DNSSEC, - dns_rdataclass_in, - &b, mctx, &dstkey); - if (result != ISC_R_SUCCESS) - return (result); - } - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) { - if (secret != NULL) { - isc_buffer_t b; - - isc_buffer_init(&b, secret, length); - isc_buffer_add(&b, length); - result = dst_key_frombuffer(name, DST_ALG_HMACSHA384, - DNS_KEYOWNER_ENTITY, - DNS_KEYPROTO_DNSSEC, - dns_rdataclass_in, - &b, mctx, &dstkey); - if (result != ISC_R_SUCCESS) - return (result); - } - } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) { - if (secret != NULL) { - isc_buffer_t b; - - isc_buffer_init(&b, secret, length); - isc_buffer_add(&b, length); - result = dst_key_frombuffer(name, DST_ALG_HMACSHA512, - DNS_KEYOWNER_ENTITY, - DNS_KEYPROTO_DNSSEC, - dns_rdataclass_in, - &b, mctx, &dstkey); - if (result != ISC_R_SUCCESS) - return (result); - } - } else if (length > 0) - return (DNS_R_BADALG); - - result = dns_tsigkey_createfromkey(name, algorithm, dstkey, - generated, creator, - inception, expire, mctx, ring, key); - if (result != ISC_R_SUCCESS && dstkey != NULL) - dst_key_free(&dstkey); - return (result); -} - -void -dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) { - REQUIRE(VALID_TSIG_KEY(source)); - REQUIRE(targetp != NULL && *targetp == NULL); - - isc_refcount_increment(&source->refs, NULL); - *targetp = source; -} - -static void -tsigkey_free(dns_tsigkey_t *key) { - REQUIRE(VALID_TSIG_KEY(key)); - - key->magic = 0; - dns_name_free(&key->name, key->mctx); - if (algname_is_allocated(key->algorithm)) { - dns_name_free(key->algorithm, key->mctx); - isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t)); - } - 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_refcount_destroy(&key->refs); - isc_mem_put(key->mctx, key, sizeof(dns_tsigkey_t)); -} - -void -dns_tsigkey_detach(dns_tsigkey_t **keyp) { - dns_tsigkey_t *key; - unsigned int refs; - - REQUIRE(keyp != NULL); - REQUIRE(VALID_TSIG_KEY(*keyp)); - - key = *keyp; - isc_refcount_decrement(&key->refs, &refs); - - if (refs == 0) - tsigkey_free(key); - - *keyp = NULL; -} - -void -dns_tsigkey_setdeleted(dns_tsigkey_t *key) { - REQUIRE(VALID_TSIG_KEY(key)); - REQUIRE(key->ring != NULL); - - RWLOCK(&key->ring->lock, isc_rwlocktype_write); - (void)dns_rbt_deletename(key->ring->keys, &key->name, ISC_FALSE); - RWUNLOCK(&key->ring->lock, isc_rwlocktype_write); -} - -static void -buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) { - isc_uint16_t valhi; - isc_uint32_t vallo; - - valhi = (isc_uint16_t)(val >> 32); - vallo = (isc_uint32_t)(val & 0xFFFFFFFF); - isc_buffer_putuint16(b, valhi); - isc_buffer_putuint32(b, vallo); -} - -isc_result_t -dns_tsig_sign(dns_message_t *msg) { - dns_tsigkey_t *key; - dns_rdata_any_tsig_t tsig, querytsig; - unsigned char data[128]; - isc_buffer_t databuf, sigbuf; - isc_buffer_t *dynbuf; - dns_name_t *owner; - dns_rdata_t *rdata = NULL; - dns_rdatalist_t *datalist; - dns_rdataset_t *dataset; - isc_region_t r; - isc_stdtime_t now; - isc_mem_t *mctx; - dst_context_t *ctx = NULL; - isc_result_t ret; - unsigned char badtimedata[BADTIMELEN]; - unsigned int sigsize = 0; - - REQUIRE(msg != NULL); - REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg))); - - /* - * If this is a response, there should be a query tsig. - */ - if (is_response(msg) && msg->querytsig == NULL) - return (DNS_R_EXPECTEDTSIG); - - dynbuf = NULL; - - mctx = msg->mctx; - 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); - dns_name_clone(key->algorithm, &tsig.algorithm); - - isc_stdtime_get(&now); - tsig.timesigned = now + msg->timeadjust; - tsig.fudge = DNS_TSIG_FUDGE; - - tsig.originalid = msg->id; - - isc_buffer_init(&databuf, data, sizeof(data)); - - if (is_response(msg)) - tsig.error = msg->querytsigstatus; - else - tsig.error = dns_rcode_noerror; - - if (tsig.error != dns_tsigerror_badtime) { - tsig.otherlen = 0; - tsig.other = NULL; - } else { - isc_buffer_t otherbuf; - - tsig.otherlen = BADTIMELEN; - tsig.other = badtimedata; - isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen); - buffer_putuint48(&otherbuf, tsig.timesigned); - } - - if (key->key != NULL && tsig.error != dns_tsigerror_badsig) { - unsigned char header[DNS_MESSAGE_HEADERLEN]; - isc_buffer_t headerbuf; - isc_uint16_t digestbits; - - ret = dst_context_create(key->key, mctx, &ctx); - if (ret != ISC_R_SUCCESS) - return (ret); - - /* - * If this is a response, digest the query signature. - */ - if (is_response(msg)) { - dns_rdata_t querytsigrdata = DNS_RDATA_INIT; - - 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_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - } - - /* - * Digest the header. - */ - isc_buffer_init(&headerbuf, header, sizeof(header)); - dns_message_renderheader(msg, &headerbuf); - isc_buffer_usedregion(&headerbuf, &r); - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - /* - * Digest the remainder of the message. - */ - isc_buffer_usedregion(msg->buffer, &r); - isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - if (msg->tcp_continuation == 0) { - /* - * Digest the name, class, ttl, alg. - */ - dns_name_toregion(&key->name, &r); - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - 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_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - dns_name_toregion(&tsig.algorithm, &r); - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - } - /* Digest the timesigned and fudge */ - isc_buffer_clear(&databuf); - if (tsig.error == dns_tsigerror_badtime) - tsig.timesigned = querytsig.timesigned; - buffer_putuint48(&databuf, tsig.timesigned); - isc_buffer_putuint16(&databuf, tsig.fudge); - isc_buffer_usedregion(&databuf, &r); - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - if (msg->tcp_continuation == 0) { - /* - * Digest the error and other data length. - */ - isc_buffer_clear(&databuf); - isc_buffer_putuint16(&databuf, tsig.error); - isc_buffer_putuint16(&databuf, tsig.otherlen); - - isc_buffer_usedregion(&databuf, &r); - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - /* - * Digest the error and other data. - */ - if (tsig.otherlen > 0) { - r.length = tsig.otherlen; - r.base = tsig.other; - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - } - } - - ret = dst_key_sigsize(key->key, &sigsize); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize); - if (tsig.signature == NULL) { - ret = ISC_R_NOMEMORY; - goto cleanup_context; - } - - isc_buffer_init(&sigbuf, tsig.signature, sigsize); - ret = dst_context_sign(ctx, &sigbuf); - if (ret != ISC_R_SUCCESS) - goto cleanup_signature; - dst_context_destroy(&ctx); - digestbits = dst_key_getbits(key->key); - if (digestbits != 0) { - unsigned int bytes = (digestbits + 1) / 8; - if (is_response(msg) && bytes < querytsig.siglen) - bytes = querytsig.siglen; - if (bytes > isc_buffer_usedlength(&sigbuf)) - bytes = isc_buffer_usedlength(&sigbuf); - tsig.siglen = bytes; - } else - tsig.siglen = isc_buffer_usedlength(&sigbuf); - } else { - tsig.siglen = 0; - tsig.signature = NULL; - } - - ret = dns_message_gettemprdata(msg, &rdata); - if (ret != ISC_R_SUCCESS) - goto cleanup_signature; - ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512); - if (ret != ISC_R_SUCCESS) - goto cleanup_rdata; - ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any, - dns_rdatatype_tsig, &tsig, dynbuf); - if (ret != ISC_R_SUCCESS) - goto cleanup_dynbuf; - - dns_message_takebuffer(msg, &dynbuf); - - if (tsig.signature != NULL) { - isc_mem_put(mctx, tsig.signature, sigsize); - tsig.signature = NULL; - } - - owner = NULL; - ret = dns_message_gettempname(msg, &owner); - if (ret != ISC_R_SUCCESS) - goto cleanup_rdata; - dns_name_init(owner, NULL); - ret = dns_name_dup(&key->name, msg->mctx, owner); - if (ret != ISC_R_SUCCESS) - goto cleanup_owner; - - datalist = NULL; - ret = dns_message_gettemprdatalist(msg, &datalist); - if (ret != ISC_R_SUCCESS) - goto cleanup_owner; - dataset = NULL; - ret = dns_message_gettemprdataset(msg, &dataset); - if (ret != ISC_R_SUCCESS) - goto cleanup_rdatalist; - datalist->rdclass = dns_rdataclass_any; - datalist->type = dns_rdatatype_tsig; - datalist->covers = 0; - datalist->ttl = 0; - ISC_LIST_INIT(datalist->rdata); - ISC_LIST_APPEND(datalist->rdata, rdata, link); - dns_rdataset_init(dataset); - RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) - == ISC_R_SUCCESS); - msg->tsig = dataset; - msg->tsigname = owner; - - return (ISC_R_SUCCESS); - - cleanup_rdatalist: - dns_message_puttemprdatalist(msg, &datalist); - cleanup_owner: - dns_message_puttempname(msg, &owner); - goto cleanup_rdata; - cleanup_dynbuf: - isc_buffer_free(&dynbuf); - cleanup_rdata: - dns_message_puttemprdata(msg, &rdata); - cleanup_signature: - if (tsig.signature != NULL) - isc_mem_put(mctx, tsig.signature, sigsize); - cleanup_context: - if (ctx != NULL) - dst_context_destroy(&ctx); - return (ret); -} - -isc_result_t -dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, - dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2) -{ - 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]; - dns_name_t *keyname; - dns_rdata_t rdata = DNS_RDATA_INIT; - isc_stdtime_t now; - isc_result_t ret; - dns_tsigkey_t *tsigkey; - dst_key_t *key = NULL; - unsigned char header[DNS_MESSAGE_HEADERLEN]; - dst_context_t *ctx = NULL; - isc_mem_t *mctx; - isc_uint16_t addcount, id; - unsigned int siglen; - unsigned int alg; - - REQUIRE(source != NULL); - REQUIRE(DNS_MESSAGE_VALID(msg)); - tsigkey = dns_message_gettsigkey(msg); - REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey)); - - msg->verify_attempted = 1; - - if (msg->tcp_continuation) { - if (tsigkey == NULL || msg->querytsig == NULL) - return (DNS_R_UNEXPECTEDTSIG); - return (tsig_verify_tcp(source, msg)); - } - - /* - * There should be a TSIG record... - */ - if (msg->tsig == NULL) - return (DNS_R_EXPECTEDTSIG); - - /* - * If this is a response and there's no key or query TSIG, there - * shouldn't be one on the response. - */ - if (is_response(msg) && - (tsigkey == NULL || msg->querytsig == NULL)) - return (DNS_R_UNEXPECTEDTSIG); - - mctx = msg->mctx; - - /* - * If we're here, we know the message is well formed and contains a - * TSIG record. - */ - - keyname = msg->tsigname; - ret = dns_rdataset_first(msg->tsig); - if (ret != ISC_R_SUCCESS) - return (ret); - dns_rdataset_current(msg->tsig, &rdata); - ret = dns_rdata_tostruct(&rdata, &tsig, NULL); - if (ret != ISC_R_SUCCESS) - return (ret); - dns_rdata_reset(&rdata); - 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, &tsigkey->name) || - !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) - { - msg->tsigstatus = dns_tsigerror_badkey; - tsig_log(msg->tsigkey, 2, - "key name and algorithm do not match"); - return (DNS_R_TSIGVERIFYFAILURE); - } - - /* - * Get the current time. - */ - isc_stdtime_get(&now); - - /* - * Find dns_tsigkey_t based on keyname. - */ - if (tsigkey == NULL) { - ret = ISC_R_NOTFOUND; - if (ring1 != NULL) - ret = dns_tsigkey_find(&tsigkey, keyname, - &tsig.algorithm, ring1); - if (ret == ISC_R_NOTFOUND && ring2 != NULL) - ret = dns_tsigkey_find(&tsigkey, keyname, - &tsig.algorithm, ring2); - if (ret != ISC_R_SUCCESS) { - msg->tsigstatus = dns_tsigerror_badkey; - ret = dns_tsigkey_create(keyname, &tsig.algorithm, - NULL, 0, ISC_FALSE, NULL, - now, now, - mctx, NULL, &msg->tsigkey); - if (ret != ISC_R_SUCCESS) - return (ret); - tsig_log(msg->tsigkey, 2, "unknown key"); - return (DNS_R_TSIGVERIFYFAILURE); - } - msg->tsigkey = tsigkey; - } - - key = tsigkey->key; - - /* - * Is the time ok? - */ - if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { - msg->tsigstatus = dns_tsigerror_badtime; - tsig_log(msg->tsigkey, 2, "signature has expired"); - return (DNS_R_CLOCKSKEW); - } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) { - msg->tsigstatus = dns_tsigerror_badtime; - tsig_log(msg->tsigkey, 2, "signature is in the future"); - return (DNS_R_CLOCKSKEW); - } - - /* - * Check digest length. - */ - alg = dst_key_alg(key); - ret = dst_key_sigsize(key, &siglen); - if (ret != ISC_R_SUCCESS) - return (ret); - if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 || - alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 || - alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) { - isc_uint16_t digestbits = dst_key_getbits(key); - if (tsig.siglen > siglen) { - tsig_log(msg->tsigkey, 2, "signature length to big"); - return (DNS_R_FORMERR); - } - if (tsig.siglen > 0 && - (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) { - tsig_log(msg->tsigkey, 2, - "signature length below minimum"); - return (DNS_R_FORMERR); - } - if (tsig.siglen > 0 && digestbits != 0 && - tsig.siglen < ((digestbits + 1) / 8)) { - msg->tsigstatus = dns_tsigerror_badtrunc; - tsig_log(msg->tsigkey, 2, - "truncated signature length too small"); - return (DNS_R_TSIGVERIFYFAILURE); - } - if (tsig.siglen > 0 && digestbits == 0 && - tsig.siglen < siglen) { - msg->tsigstatus = dns_tsigerror_badtrunc; - tsig_log(msg->tsigkey, 2, "signature length too small"); - return (DNS_R_TSIGVERIFYFAILURE); - } - } - - if (tsig.siglen > 0) { - sig_r.base = tsig.signature; - sig_r.length = tsig.siglen; - - ret = dst_context_create(key, mctx, &ctx); - if (ret != ISC_R_SUCCESS) - return (ret); - - if (is_response(msg)) { - isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, querytsig.siglen); - isc_buffer_usedregion(&databuf, &r); - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - 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_context; - } - } - - /* - * Extract the header. - */ - isc_buffer_usedregion(source, &r); - memcpy(header, r.base, DNS_MESSAGE_HEADERLEN); - isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); - - /* - * Decrement the additional field counter. - */ - memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); - addcount = htons((isc_uint16_t)(ntohs(addcount) - 1)); - memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); - - /* - * Put in the original id. - */ - id = htons(tsig.originalid); - memcpy(&header[0], &id, 2); - - /* - * Digest the modified header. - */ - header_r.base = (unsigned char *) header; - header_r.length = DNS_MESSAGE_HEADERLEN; - ret = dst_context_adddata(ctx, &header_r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - /* - * Digest all non-TSIG records. - */ - isc_buffer_usedregion(source, &source_r); - r.base = source_r.base + DNS_MESSAGE_HEADERLEN; - r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - /* - * Digest the key name. - */ - dns_name_toregion(&tsigkey->name, &r); - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, tsig.common.rdclass); - isc_buffer_putuint32(&databuf, msg->tsig->ttl); - isc_buffer_usedregion(&databuf, &r); - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - /* - * Digest the key algorithm. - */ - dns_name_toregion(tsigkey->algorithm, &r); - ret = dst_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - isc_buffer_clear(&databuf); - buffer_putuint48(&databuf, tsig.timesigned); - 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_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_context_adddata(ctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - } - - ret = dst_context_verify(ctx, &sig_r); - if (ret == DST_R_VERIFYFAILURE) { - msg->tsigstatus = dns_tsigerror_badsig; - ret = DNS_R_TSIGVERIFYFAILURE; - tsig_log(msg->tsigkey, 2, - "signature failed to verify"); - goto cleanup_context; - } else if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - dst_context_destroy(&ctx); - } else if (tsig.error != dns_tsigerror_badsig && - tsig.error != dns_tsigerror_badkey) - { - msg->tsigstatus = dns_tsigerror_badsig; - tsig_log(msg->tsigkey, 2, "signature was empty"); - return (DNS_R_TSIGVERIFYFAILURE); - } - - msg->tsigstatus = dns_rcode_noerror; - - if (tsig.error != dns_rcode_noerror) { - if (tsig.error == dns_tsigerror_badtime) - return (DNS_R_CLOCKSKEW); - else - return (DNS_R_TSIGERRORSET); - } - - msg->verified_sig = 1; - - return (ISC_R_SUCCESS); - -cleanup_context: - if (ctx != NULL) - dst_context_destroy(&ctx); - - return (ret); -} - -static isc_result_t -tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) { - 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]; - dns_name_t *keyname; - dns_rdata_t rdata = DNS_RDATA_INIT; - isc_stdtime_t now; - isc_result_t ret; - dns_tsigkey_t *tsigkey; - dst_key_t *key = NULL; - unsigned char header[DNS_MESSAGE_HEADERLEN]; - isc_uint16_t addcount, id; - isc_boolean_t has_tsig = ISC_FALSE; - isc_mem_t *mctx; - - REQUIRE(source != NULL); - REQUIRE(msg != NULL); - REQUIRE(dns_message_gettsigkey(msg) != NULL); - REQUIRE(msg->tcp_continuation == 1); - REQUIRE(msg->querytsig != NULL); - - if (!is_response(msg)) - return (DNS_R_EXPECTEDRESPONSE); - - mctx = msg->mctx; - - tsigkey = dns_message_gettsigkey(msg); - - /* - * Extract and parse the previous TSIG - */ - 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); - dns_rdata_reset(&rdata); - - /* - * If there is a TSIG in this message, do some checks. - */ - if (msg->tsig != NULL) { - has_tsig = ISC_TRUE; - - keyname = msg->tsigname; - ret = dns_rdataset_first(msg->tsig); - if (ret != ISC_R_SUCCESS) - goto cleanup_querystruct; - dns_rdataset_current(msg->tsig, &rdata); - ret = dns_rdata_tostruct(&rdata, &tsig, NULL); - if (ret != ISC_R_SUCCESS) - goto cleanup_querystruct; - - /* - * Do the key name and algorithm match that of the query? - */ - if (!dns_name_equal(keyname, &tsigkey->name) || - !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) - { - msg->tsigstatus = dns_tsigerror_badkey; - ret = DNS_R_TSIGVERIFYFAILURE; - tsig_log(msg->tsigkey, 2, - "key name and algorithm do not match"); - goto cleanup_querystruct; - } - - /* - * Is the time ok? - */ - isc_stdtime_get(&now); - - if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) { - msg->tsigstatus = dns_tsigerror_badtime; - tsig_log(msg->tsigkey, 2, "signature has expired"); - ret = DNS_R_CLOCKSKEW; - goto cleanup_querystruct; - } else if (now + msg->timeadjust < - tsig.timesigned - tsig.fudge) - { - msg->tsigstatus = dns_tsigerror_badtime; - tsig_log(msg->tsigkey, 2, - "signature is in the future"); - ret = DNS_R_CLOCKSKEW; - goto cleanup_querystruct; - } - } - - key = tsigkey->key; - - if (msg->tsigctx == NULL) { - ret = dst_context_create(key, mctx, &msg->tsigctx); - if (ret != ISC_R_SUCCESS) - goto cleanup_querystruct; - - /* - * Digest the length of the query signature - */ - isc_buffer_init(&databuf, data, sizeof(data)); - isc_buffer_putuint16(&databuf, querytsig.siglen); - isc_buffer_usedregion(&databuf, &r); - ret = dst_context_adddata(msg->tsigctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - /* - * Digest the data of the query signature - */ - 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_context; - } - } - - /* - * Extract the header. - */ - isc_buffer_usedregion(source, &r); - memcpy(header, r.base, DNS_MESSAGE_HEADERLEN); - isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); - - /* - * Decrement the additional field counter if necessary. - */ - if (has_tsig) { - memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); - addcount = htons((isc_uint16_t)(ntohs(addcount) - 1)); - memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); - } - - /* - * Put in the original id. - */ - /* XXX Can TCP transfers be forwarded? How would that work? */ - if (has_tsig) { - id = htons(tsig.originalid); - memcpy(&header[0], &id, 2); - } - - /* - * Digest the modified header. - */ - header_r.base = (unsigned char *) header; - header_r.length = DNS_MESSAGE_HEADERLEN; - ret = dst_context_adddata(msg->tsigctx, &header_r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - /* - * Digest all non-TSIG records. - */ - isc_buffer_usedregion(source, &source_r); - r.base = source_r.base + DNS_MESSAGE_HEADERLEN; - if (has_tsig) - r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; - else - r.length = source_r.length - DNS_MESSAGE_HEADERLEN; - ret = dst_context_adddata(msg->tsigctx, &r); - if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - /* - * Digest the time signed and fudge. - */ - if (has_tsig) { - isc_buffer_init(&databuf, data, sizeof(data)); - buffer_putuint48(&databuf, tsig.timesigned); - isc_buffer_putuint16(&databuf, tsig.fudge); - isc_buffer_usedregion(&databuf, &r); - 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) { - if (tsig.error == dns_tsigerror_badtime) - ret = DNS_R_CLOCKSKEW; - else - ret = DNS_R_TSIGERRORSET; - } else { - tsig_log(msg->tsigkey, 2, - "signature is empty"); - ret = DNS_R_TSIGVERIFYFAILURE; - } - goto cleanup_context; - } - - ret = dst_context_verify(msg->tsigctx, &sig_r); - if (ret == DST_R_VERIFYFAILURE) { - msg->tsigstatus = dns_tsigerror_badsig; - tsig_log(msg->tsigkey, 2, - "signature failed to verify"); - ret = DNS_R_TSIGVERIFYFAILURE; - goto cleanup_context; - } - else if (ret != ISC_R_SUCCESS) - goto cleanup_context; - - dst_context_destroy(&msg->tsigctx); - } - - msg->tsigstatus = dns_rcode_noerror; - return (ISC_R_SUCCESS); - - cleanup_context: - dst_context_destroy(&msg->tsigctx); - - cleanup_querystruct: - dns_rdata_freestruct(&querytsig); - - return (ret); - -} - -isc_result_t -dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name, - dns_name_t *algorithm, dns_tsig_keyring_t *ring) -{ - dns_tsigkey_t *key; - isc_stdtime_t now; - isc_result_t result; - - REQUIRE(tsigkey != NULL); - REQUIRE(*tsigkey == NULL); - REQUIRE(name != NULL); - REQUIRE(ring != NULL); - - isc_stdtime_get(&now); - RWLOCK(&ring->lock, isc_rwlocktype_read); - key = NULL; - result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key); - if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) { - RWUNLOCK(&ring->lock, isc_rwlocktype_read); - return (ISC_R_NOTFOUND); - } - if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) { - RWUNLOCK(&ring->lock, isc_rwlocktype_read); - return (ISC_R_NOTFOUND); - } - if (key->inception != key->expire && key->expire < now) { - /* - * The key has expired. - */ - RWUNLOCK(&ring->lock, isc_rwlocktype_read); - RWLOCK(&ring->lock, isc_rwlocktype_write); - (void) dns_rbt_deletename(ring->keys, name, ISC_FALSE); - RWUNLOCK(&ring->lock, isc_rwlocktype_write); - return (ISC_R_NOTFOUND); - } - - isc_refcount_increment(&key->refs, NULL); - RWUNLOCK(&ring->lock, isc_rwlocktype_read); - *tsigkey = key; - return (ISC_R_SUCCESS); -} - -static void -free_tsignode(void *node, void *_unused) { - dns_tsigkey_t *key; - - UNUSED(_unused); - - REQUIRE(node != NULL); - - key = node; - dns_tsigkey_detach(&key); -} - -isc_result_t -dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) { - isc_result_t result; - dns_tsig_keyring_t *ring; - - REQUIRE(mctx != NULL); - REQUIRE(ringp != NULL); - REQUIRE(*ringp == NULL); - - ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t)); - if (ring == NULL) - return (ISC_R_NOMEMORY); - - result = isc_rwlock_init(&ring->lock, 0, 0); - if (result != ISC_R_SUCCESS) { - isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t)); - return (result); - } - - ring->keys = NULL; - result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys); - if (result != ISC_R_SUCCESS) { - isc_rwlock_destroy(&ring->lock); - isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t)); - return (result); - } - - ring->mctx = mctx; - - *ringp = ring; - return (ISC_R_SUCCESS); -} - -void -dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp) { - dns_tsig_keyring_t *ring; - - REQUIRE(ringp != NULL); - REQUIRE(*ringp != NULL); - - ring = *ringp; - *ringp = NULL; - - dns_rbt_destroy(&ring->keys); - isc_rwlock_destroy(&ring->lock); - isc_mem_put(ring->mctx, ring, sizeof(dns_tsig_keyring_t)); -} |