PageRenderTime 135ms CodeModel.GetById 36ms app.highlight 87ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/bind9/lib/dns/tsig.c

https://bitbucket.org/freebsd/freebsd-head/
C | 1857 lines | 1459 code | 232 blank | 166 comment | 524 complexity | f1e6eeeab52c057958c6131f0fc8092c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
   3 * Copyright (C) 1999-2002  Internet Software Consortium.
   4 *
   5 * Permission to use, copy, modify, and/or distribute this software for any
   6 * purpose with or without fee is hereby granted, provided that the above
   7 * copyright notice and this permission notice appear in all copies.
   8 *
   9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15 * PERFORMANCE OF THIS SOFTWARE.
  16 */
  17
  18/*
  19 * $Id$
  20 */
  21/*! \file */
  22#include <config.h>
  23#include <stdlib.h>
  24
  25#include <isc/buffer.h>
  26#include <isc/mem.h>
  27#include <isc/print.h>
  28#include <isc/refcount.h>
  29#include <isc/serial.h>
  30#include <isc/string.h>		/* Required for HP/UX (and others?) */
  31#include <isc/util.h>
  32#include <isc/time.h>
  33
  34#include <dns/keyvalues.h>
  35#include <dns/log.h>
  36#include <dns/message.h>
  37#include <dns/fixedname.h>
  38#include <dns/rbt.h>
  39#include <dns/rdata.h>
  40#include <dns/rdatalist.h>
  41#include <dns/rdataset.h>
  42#include <dns/rdatastruct.h>
  43#include <dns/result.h>
  44#include <dns/tsig.h>
  45
  46#include <dst/result.h>
  47
  48#define TSIG_MAGIC		ISC_MAGIC('T', 'S', 'I', 'G')
  49#define VALID_TSIG_KEY(x)	ISC_MAGIC_VALID(x, TSIG_MAGIC)
  50
  51#ifndef DNS_TSIG_MAXGENERATEDKEYS
  52#define DNS_TSIG_MAXGENERATEDKEYS 4096
  53#endif
  54
  55#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
  56#define algname_is_allocated(algname) \
  57	((algname) != dns_tsig_hmacmd5_name && \
  58	 (algname) != dns_tsig_hmacsha1_name && \
  59	 (algname) != dns_tsig_hmacsha224_name && \
  60	 (algname) != dns_tsig_hmacsha256_name && \
  61	 (algname) != dns_tsig_hmacsha384_name && \
  62	 (algname) != dns_tsig_hmacsha512_name && \
  63	 (algname) != dns_tsig_gssapi_name && \
  64	 (algname) != dns_tsig_gssapims_name)
  65
  66#define BADTIMELEN 6
  67
  68static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";
  69static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };
  70
  71static dns_name_t hmacmd5 = {
  72	DNS_NAME_MAGIC,
  73	hmacmd5_ndata, 26, 5,
  74	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
  75	hmacmd5_offsets, NULL,
  76	{(void *)-1, (void *)-1},
  77	{NULL, NULL}
  78};
  79
  80dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
  81
  82static unsigned char gsstsig_ndata[] = "\010gss-tsig";
  83static unsigned char gsstsig_offsets[] = { 0, 9 };
  84static dns_name_t gsstsig = {
  85	DNS_NAME_MAGIC,
  86	gsstsig_ndata, 10, 2,
  87	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
  88	gsstsig_offsets, NULL,
  89	{(void *)-1, (void *)-1},
  90	{NULL, NULL}
  91};
  92LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
  93
  94/*
  95 * Since Microsoft doesn't follow its own standard, we will use this
  96 * alternate name as a second guess.
  97 */
  98static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
  99static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
 100static dns_name_t gsstsigms = {
 101	DNS_NAME_MAGIC,
 102	gsstsigms_ndata, 19, 4,
 103	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
 104	gsstsigms_offsets, NULL,
 105	{(void *)-1, (void *)-1},
 106	{NULL, NULL}
 107};
 108LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
 109
 110static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
 111static unsigned char hmacsha1_offsets[] = { 0, 10 };
 112
 113static dns_name_t  hmacsha1 = {
 114	DNS_NAME_MAGIC,
 115	hmacsha1_ndata, 11, 2,
 116	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
 117	hmacsha1_offsets, NULL,
 118	{(void *)-1, (void *)-1},
 119	{NULL, NULL}
 120};
 121
 122LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
 123
 124static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
 125static unsigned char hmacsha224_offsets[] = { 0, 12 };
 126
 127static dns_name_t hmacsha224 = {
 128	DNS_NAME_MAGIC,
 129	hmacsha224_ndata, 13, 2,
 130	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
 131	hmacsha224_offsets, NULL,
 132	{(void *)-1, (void *)-1},
 133	{NULL, NULL}
 134};
 135
 136LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
 137
 138static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
 139static unsigned char hmacsha256_offsets[] = { 0, 12 };
 140
 141static dns_name_t hmacsha256 = {
 142	DNS_NAME_MAGIC,
 143	hmacsha256_ndata, 13, 2,
 144	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
 145	hmacsha256_offsets, NULL,
 146	{(void *)-1, (void *)-1},
 147	{NULL, NULL}
 148};
 149
 150LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
 151
 152static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
 153static unsigned char hmacsha384_offsets[] = { 0, 12 };
 154
 155static dns_name_t hmacsha384 = {
 156	DNS_NAME_MAGIC,
 157	hmacsha384_ndata, 13, 2,
 158	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
 159	hmacsha384_offsets, NULL,
 160	{(void *)-1, (void *)-1},
 161	{NULL, NULL}
 162};
 163
 164LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
 165
 166static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
 167static unsigned char hmacsha512_offsets[] = { 0, 12 };
 168
 169static dns_name_t hmacsha512 = {
 170	DNS_NAME_MAGIC,
 171	hmacsha512_ndata, 13, 2,
 172	DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
 173	hmacsha512_offsets, NULL,
 174	{(void *)-1, (void *)-1},
 175	{NULL, NULL}
 176};
 177
 178LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
 179
 180static isc_result_t
 181tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
 182
 183static void
 184tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
 185     ISC_FORMAT_PRINTF(3, 4);
 186
 187static void
 188cleanup_ring(dns_tsig_keyring_t *ring);
 189static void
 190tsigkey_free(dns_tsigkey_t *key);
 191
 192static void
 193tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
 194	va_list ap;
 195	char message[4096];
 196	char namestr[DNS_NAME_FORMATSIZE];
 197	char creatorstr[DNS_NAME_FORMATSIZE];
 198
 199	if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
 200		return;
 201	if (key != NULL)
 202		dns_name_format(&key->name, namestr, sizeof(namestr));
 203	else
 204		strcpy(namestr, "<null>");
 205
 206	if (key != NULL && key->generated && key->creator)
 207		dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
 208	else
 209		strcpy(creatorstr, "<null>");
 210
 211	va_start(ap, fmt);
 212	vsnprintf(message, sizeof(message), fmt, ap);
 213	va_end(ap);
 214	if (key != NULL && key->generated)
 215		isc_log_write(dns_lctx,
 216			      DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
 217			      level, "tsig key '%s' (%s): %s",
 218			      namestr, creatorstr, message);
 219	else
 220		isc_log_write(dns_lctx,
 221			      DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
 222			      level, "tsig key '%s': %s", namestr, message);
 223}
 224
 225static void
 226remove_fromring(dns_tsigkey_t *tkey) {
 227	if (tkey->generated) {
 228		ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
 229		tkey->ring->generated--;
 230	}
 231	(void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
 232}
 233
 234static void
 235adjust_lru(dns_tsigkey_t *tkey) {
 236	if (tkey->generated) {
 237		RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
 238		/*
 239		 * We may have been removed from the LRU list between
 240		 * removing the read lock and aquiring the write lock.
 241		 */
 242		if (ISC_LINK_LINKED(tkey, link)) {
 243			ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
 244			ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
 245		}
 246		RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
 247	}
 248}
 249
 250/*
 251 * A supplemental routine just to add a key to ring.  Note that reference
 252 * counter should be counted separately because we may be adding the key
 253 * as part of creation of the key, in which case the reference counter was
 254 * already initialized.  Also note we don't need RWLOCK for the reference
 255 * counter: it's protected by a separate lock.
 256 */
 257static isc_result_t
 258keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
 259	    dns_tsigkey_t *tkey)
 260{
 261	isc_result_t result;
 262
 263	RWLOCK(&ring->lock, isc_rwlocktype_write);
 264	ring->writecount++;
 265
 266	/*
 267	 * Do on the fly cleaning.  Find some nodes we might not
 268	 * want around any more.
 269	 */
 270	if (ring->writecount > 10) {
 271		cleanup_ring(ring);
 272		ring->writecount = 0;
 273	}
 274
 275	result = dns_rbt_addname(ring->keys, name, tkey);
 276	if (tkey->generated) {
 277		/*
 278		 * Add the new key to the LRU list and remove the least
 279		 * recently used key if there are too many keys on the list.
 280		 */
 281		ISC_LIST_INITANDAPPEND(ring->lru, tkey, link);
 282		if (ring->generated++ > ring->maxgenerated)
 283			remove_fromring(ISC_LIST_HEAD(ring->lru));
 284	}
 285	RWUNLOCK(&ring->lock, isc_rwlocktype_write);
 286
 287	return (result);
 288}
 289
 290isc_result_t
 291dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
 292			  dst_key_t *dstkey, isc_boolean_t generated,
 293			  dns_name_t *creator, isc_stdtime_t inception,
 294			  isc_stdtime_t expire, isc_mem_t *mctx,
 295			  dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
 296{
 297	dns_tsigkey_t *tkey;
 298	isc_result_t ret;
 299	unsigned int refs = 0;
 300
 301	REQUIRE(key == NULL || *key == NULL);
 302	REQUIRE(name != NULL);
 303	REQUIRE(algorithm != NULL);
 304	REQUIRE(mctx != NULL);
 305	REQUIRE(key != NULL || ring != NULL);
 306
 307	tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
 308	if (tkey == NULL)
 309		return (ISC_R_NOMEMORY);
 310
 311	dns_name_init(&tkey->name, NULL);
 312	ret = dns_name_dup(name, mctx, &tkey->name);
 313	if (ret != ISC_R_SUCCESS)
 314		goto cleanup_key;
 315	(void)dns_name_downcase(&tkey->name, &tkey->name, NULL);
 316
 317	if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
 318		tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
 319		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
 320			ret = DNS_R_BADALG;
 321			goto cleanup_name;
 322		}
 323	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
 324		tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
 325		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
 326			ret = DNS_R_BADALG;
 327			goto cleanup_name;
 328		}
 329	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
 330		tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
 331		if (dstkey != NULL &&
 332		    dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
 333			ret = DNS_R_BADALG;
 334			goto cleanup_name;
 335		}
 336	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
 337		tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
 338		if (dstkey != NULL &&
 339		    dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
 340			ret = DNS_R_BADALG;
 341			goto cleanup_name;
 342		}
 343	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
 344		tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
 345		if (dstkey != NULL &&
 346		    dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
 347			ret = DNS_R_BADALG;
 348			goto cleanup_name;
 349		}
 350	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
 351		tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
 352		if (dstkey != NULL &&
 353		    dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
 354			ret = DNS_R_BADALG;
 355			goto cleanup_name;
 356		}
 357	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
 358		tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
 359		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
 360			ret = DNS_R_BADALG;
 361			goto cleanup_name;
 362		}
 363	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
 364		tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
 365		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
 366			ret = DNS_R_BADALG;
 367			goto cleanup_name;
 368		}
 369	} else {
 370		if (dstkey != NULL) {
 371			ret = DNS_R_BADALG;
 372			goto cleanup_name;
 373		}
 374		tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
 375		if (tkey->algorithm == NULL) {
 376			ret = ISC_R_NOMEMORY;
 377			goto cleanup_name;
 378		}
 379		dns_name_init(tkey->algorithm, NULL);
 380		ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
 381		if (ret != ISC_R_SUCCESS)
 382			goto cleanup_algorithm;
 383		(void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
 384					NULL);
 385	}
 386
 387	if (creator != NULL) {
 388		tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
 389		if (tkey->creator == NULL) {
 390			ret = ISC_R_NOMEMORY;
 391			goto cleanup_algorithm;
 392		}
 393		dns_name_init(tkey->creator, NULL);
 394		ret = dns_name_dup(creator, mctx, tkey->creator);
 395		if (ret != ISC_R_SUCCESS) {
 396			isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
 397			goto cleanup_algorithm;
 398		}
 399	} else
 400		tkey->creator = NULL;
 401
 402	tkey->key = NULL;
 403	if (dstkey != NULL)
 404		dst_key_attach(dstkey, &tkey->key);
 405	tkey->ring = ring;
 406
 407	if (key != NULL)
 408		refs = 1;
 409	if (ring != NULL)
 410		refs++;
 411	ret = isc_refcount_init(&tkey->refs, refs);
 412	if (ret != ISC_R_SUCCESS)
 413		goto cleanup_creator;
 414
 415	tkey->generated = generated;
 416	tkey->inception = inception;
 417	tkey->expire = expire;
 418	tkey->mctx = NULL;
 419	isc_mem_attach(mctx, &tkey->mctx);
 420
 421	tkey->magic = TSIG_MAGIC;
 422
 423	if (ring != NULL) {
 424		ret = keyring_add(ring, name, tkey);
 425		if (ret != ISC_R_SUCCESS)
 426			goto cleanup_refs;
 427	}
 428
 429	/*
 430	 * Ignore this if it's a GSS key, since the key size is meaningless.
 431	 */
 432	if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
 433	    !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
 434	    !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
 435		char namestr[DNS_NAME_FORMATSIZE];
 436		dns_name_format(name, namestr, sizeof(namestr));
 437		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
 438			      DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
 439			      "the key '%s' is too short to be secure",
 440			      namestr);
 441	}
 442
 443	if (key != NULL)
 444		*key = tkey;
 445
 446	return (ISC_R_SUCCESS);
 447
 448 cleanup_refs:
 449	tkey->magic = 0;
 450	while (refs-- > 0)
 451		isc_refcount_decrement(&tkey->refs, NULL);
 452	isc_refcount_destroy(&tkey->refs);
 453 cleanup_creator:
 454	if (tkey->key != NULL)
 455		dst_key_free(&tkey->key);
 456	if (tkey->creator != NULL) {
 457		dns_name_free(tkey->creator, mctx);
 458		isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
 459	}
 460 cleanup_algorithm:
 461	if (algname_is_allocated(tkey->algorithm)) {
 462		if (dns_name_dynamic(tkey->algorithm))
 463			dns_name_free(tkey->algorithm, mctx);
 464		isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
 465	}
 466 cleanup_name:
 467	dns_name_free(&tkey->name, mctx);
 468 cleanup_key:
 469	isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));
 470
 471	return (ret);
 472}
 473
 474/*
 475 * Find a few nodes to destroy if possible.
 476 */
 477static void
 478cleanup_ring(dns_tsig_keyring_t *ring)
 479{
 480	isc_result_t result;
 481	dns_rbtnodechain_t chain;
 482	dns_name_t foundname;
 483	dns_fixedname_t fixedorigin;
 484	dns_name_t *origin;
 485	isc_stdtime_t now;
 486	dns_rbtnode_t *node;
 487	dns_tsigkey_t *tkey;
 488
 489	/*
 490	 * Start up a new iterator each time.
 491	 */
 492	isc_stdtime_get(&now);
 493	dns_name_init(&foundname, NULL);
 494	dns_fixedname_init(&fixedorigin);
 495	origin = dns_fixedname_name(&fixedorigin);
 496
 497 again:
 498	dns_rbtnodechain_init(&chain, ring->mctx);
 499	result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
 500					origin);
 501	if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
 502		dns_rbtnodechain_invalidate(&chain);
 503		return;
 504	}
 505
 506	for (;;) {
 507		node = NULL;
 508		dns_rbtnodechain_current(&chain, &foundname, origin, &node);
 509		tkey = node->data;
 510		if (tkey != NULL) {
 511			if (tkey->generated
 512			    && isc_refcount_current(&tkey->refs) == 1
 513			    && tkey->inception != tkey->expire
 514			    && tkey->expire < now) {
 515				tsig_log(tkey, 2, "tsig expire: deleting");
 516				/* delete the key */
 517				dns_rbtnodechain_invalidate(&chain);
 518				remove_fromring(tkey);
 519				goto again;
 520			}
 521		}
 522		result = dns_rbtnodechain_next(&chain, &foundname,
 523					       origin);
 524		if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
 525			dns_rbtnodechain_invalidate(&chain);
 526			return;
 527		}
 528	}
 529}
 530
 531static void
 532destroyring(dns_tsig_keyring_t *ring) {
 533	dns_rbt_destroy(&ring->keys);
 534	isc_rwlock_destroy(&ring->lock);
 535	isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t));
 536}
 537
 538static unsigned int
 539dst_alg_fromname(dns_name_t *algorithm) {
 540	if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
 541		return (DST_ALG_HMACMD5);
 542	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
 543		return (DST_ALG_HMACSHA1);
 544	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
 545		return (DST_ALG_HMACSHA224);
 546	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
 547		return (DST_ALG_HMACSHA256);
 548	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
 549		return (DST_ALG_HMACSHA384);
 550	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
 551		return (DST_ALG_HMACSHA512);
 552	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
 553		return (DST_ALG_GSSAPI);
 554	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
 555		return (DST_ALG_GSSAPI);
 556	} else
 557		return (0);
 558}
 559
 560static isc_result_t
 561restore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) {
 562	dst_key_t *dstkey = NULL;
 563	char namestr[1024];
 564	char creatorstr[1024];
 565	char algorithmstr[1024];
 566	char keystr[4096];
 567	unsigned int inception, expire;
 568	int n;
 569	isc_buffer_t b;
 570	dns_name_t *name, *creator, *algorithm;
 571	dns_fixedname_t fname, fcreator, falgorithm;
 572	isc_result_t result;
 573	unsigned int dstalg;
 574
 575	n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr,
 576		   creatorstr, &inception, &expire, algorithmstr, keystr);
 577	if (n == EOF)
 578		return (ISC_R_NOMORE);
 579	if (n != 6)
 580		return (ISC_R_FAILURE);
 581
 582	if (isc_serial_lt(expire, now))
 583		return (DNS_R_EXPIRED);
 584
 585	dns_fixedname_init(&fname);
 586	name = dns_fixedname_name(&fname);
 587	isc_buffer_init(&b, namestr, strlen(namestr));
 588	isc_buffer_add(&b, strlen(namestr));
 589	result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
 590	if (result != ISC_R_SUCCESS)
 591		return (result);
 592
 593	dns_fixedname_init(&fcreator);
 594	creator = dns_fixedname_name(&fcreator);
 595	isc_buffer_init(&b, creatorstr, strlen(creatorstr));
 596	isc_buffer_add(&b, strlen(creatorstr));
 597	result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL);
 598	if (result != ISC_R_SUCCESS)
 599		return (result);
 600
 601	dns_fixedname_init(&falgorithm);
 602	algorithm = dns_fixedname_name(&falgorithm);
 603	isc_buffer_init(&b, algorithmstr, strlen(algorithmstr));
 604	isc_buffer_add(&b, strlen(algorithmstr));
 605	result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL);
 606	if (result != ISC_R_SUCCESS)
 607		return (result);
 608
 609	dstalg = dst_alg_fromname(algorithm);
 610	if (dstalg == 0)
 611		return (DNS_R_BADALG);
 612
 613	result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY,
 614				 DNS_KEYPROTO_DNSSEC, dns_rdataclass_in,
 615				 ring->mctx, keystr, &dstkey);
 616	if (result != ISC_R_SUCCESS)
 617		return (result);
 618
 619	result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
 620					   ISC_TRUE, creator, inception,
 621					   expire, ring->mctx, ring, NULL);
 622	if (dstkey != NULL)
 623		dst_key_free(&dstkey);
 624	return (result);
 625}
 626
 627static void
 628dump_key(dns_tsigkey_t *tkey, FILE *fp)
 629{
 630	char *buffer = NULL;
 631	int length = 0;
 632	char namestr[DNS_NAME_FORMATSIZE];
 633	char creatorstr[DNS_NAME_FORMATSIZE];
 634	char algorithmstr[DNS_NAME_FORMATSIZE];
 635	isc_result_t result;
 636
 637	dns_name_format(&tkey->name, namestr, sizeof(namestr));
 638	dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr));
 639	dns_name_format(tkey->algorithm, algorithmstr, sizeof(algorithmstr));
 640	result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length);
 641	if (result == ISC_R_SUCCESS)
 642		fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr,
 643			tkey->inception, tkey->expire, algorithmstr,
 644			length, buffer);
 645	if (buffer != NULL)
 646		isc_mem_put(tkey->mctx, buffer, length);
 647}
 648
 649isc_result_t
 650dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) {
 651	isc_result_t result;
 652	dns_rbtnodechain_t chain;
 653	dns_name_t foundname;
 654	dns_fixedname_t fixedorigin;
 655	dns_name_t *origin;
 656	isc_stdtime_t now;
 657	dns_rbtnode_t *node;
 658	dns_tsigkey_t *tkey;
 659	dns_tsig_keyring_t *ring;
 660	unsigned int references;
 661
 662	REQUIRE(ringp != NULL && *ringp != NULL);
 663
 664	ring = *ringp;
 665	*ringp = NULL;
 666
 667	RWLOCK(&ring->lock, isc_rwlocktype_write);
 668	INSIST(ring->references > 0);
 669	ring->references--;
 670	references = ring->references;
 671	RWUNLOCK(&ring->lock, isc_rwlocktype_write);
 672
 673	if (references != 0)
 674		return (DNS_R_CONTINUE);
 675
 676	isc_stdtime_get(&now);
 677	dns_name_init(&foundname, NULL);
 678	dns_fixedname_init(&fixedorigin);
 679	origin = dns_fixedname_name(&fixedorigin);
 680	dns_rbtnodechain_init(&chain, ring->mctx);
 681	result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
 682					origin);
 683	if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
 684		dns_rbtnodechain_invalidate(&chain);
 685		goto destroy;
 686	}
 687
 688	for (;;) {
 689		node = NULL;
 690		dns_rbtnodechain_current(&chain, &foundname, origin, &node);
 691		tkey = node->data;
 692		if (tkey != NULL && tkey->generated && tkey->expire >= now)
 693			dump_key(tkey, fp);
 694		result = dns_rbtnodechain_next(&chain, &foundname,
 695					       origin);
 696		if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
 697			dns_rbtnodechain_invalidate(&chain);
 698			if (result == ISC_R_NOMORE)
 699				result = ISC_R_SUCCESS;
 700			goto destroy;
 701		}
 702	}
 703
 704 destroy:
 705	destroyring(ring);
 706	return (result);
 707}
 708
 709isc_result_t
 710dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
 711		   unsigned char *secret, int length, isc_boolean_t generated,
 712		   dns_name_t *creator, isc_stdtime_t inception,
 713		   isc_stdtime_t expire, isc_mem_t *mctx,
 714		   dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
 715{
 716	dst_key_t *dstkey = NULL;
 717	isc_result_t result;
 718
 719	REQUIRE(length >= 0);
 720	if (length > 0)
 721		REQUIRE(secret != NULL);
 722
 723	if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
 724		if (secret != NULL) {
 725			isc_buffer_t b;
 726
 727			isc_buffer_init(&b, secret, length);
 728			isc_buffer_add(&b, length);
 729			result = dst_key_frombuffer(name, DST_ALG_HMACMD5,
 730						    DNS_KEYOWNER_ENTITY,
 731						    DNS_KEYPROTO_DNSSEC,
 732						    dns_rdataclass_in,
 733						    &b, mctx, &dstkey);
 734				if (result != ISC_R_SUCCESS)
 735					return (result);
 736		}
 737	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
 738		if (secret != NULL) {
 739			isc_buffer_t b;
 740
 741			isc_buffer_init(&b, secret, length);
 742			isc_buffer_add(&b, length);
 743			result = dst_key_frombuffer(name, DST_ALG_HMACSHA1,
 744						    DNS_KEYOWNER_ENTITY,
 745						    DNS_KEYPROTO_DNSSEC,
 746						    dns_rdataclass_in,
 747						    &b, mctx, &dstkey);
 748				if (result != ISC_R_SUCCESS)
 749					return (result);
 750		}
 751	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
 752		if (secret != NULL) {
 753			isc_buffer_t b;
 754
 755			isc_buffer_init(&b, secret, length);
 756			isc_buffer_add(&b, length);
 757			result = dst_key_frombuffer(name, DST_ALG_HMACSHA224,
 758						    DNS_KEYOWNER_ENTITY,
 759						    DNS_KEYPROTO_DNSSEC,
 760						    dns_rdataclass_in,
 761						    &b, mctx, &dstkey);
 762				if (result != ISC_R_SUCCESS)
 763					return (result);
 764		}
 765	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
 766		if (secret != NULL) {
 767			isc_buffer_t b;
 768
 769			isc_buffer_init(&b, secret, length);
 770			isc_buffer_add(&b, length);
 771			result = dst_key_frombuffer(name, DST_ALG_HMACSHA256,
 772						    DNS_KEYOWNER_ENTITY,
 773						    DNS_KEYPROTO_DNSSEC,
 774						    dns_rdataclass_in,
 775						    &b, mctx, &dstkey);
 776				if (result != ISC_R_SUCCESS)
 777					return (result);
 778		}
 779	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
 780		if (secret != NULL) {
 781			isc_buffer_t b;
 782
 783			isc_buffer_init(&b, secret, length);
 784			isc_buffer_add(&b, length);
 785			result = dst_key_frombuffer(name, DST_ALG_HMACSHA384,
 786						    DNS_KEYOWNER_ENTITY,
 787						    DNS_KEYPROTO_DNSSEC,
 788						    dns_rdataclass_in,
 789						    &b, mctx, &dstkey);
 790				if (result != ISC_R_SUCCESS)
 791					return (result);
 792		}
 793	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
 794		if (secret != NULL) {
 795			isc_buffer_t b;
 796
 797			isc_buffer_init(&b, secret, length);
 798			isc_buffer_add(&b, length);
 799			result = dst_key_frombuffer(name, DST_ALG_HMACSHA512,
 800						    DNS_KEYOWNER_ENTITY,
 801						    DNS_KEYPROTO_DNSSEC,
 802						    dns_rdataclass_in,
 803						    &b, mctx, &dstkey);
 804				if (result != ISC_R_SUCCESS)
 805					return (result);
 806		}
 807	} else if (length > 0)
 808		return (DNS_R_BADALG);
 809
 810	result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
 811					   generated, creator,
 812					   inception, expire, mctx, ring, key);
 813	if (dstkey != NULL)
 814		dst_key_free(&dstkey);
 815	return (result);
 816}
 817
 818void
 819dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
 820	REQUIRE(VALID_TSIG_KEY(source));
 821	REQUIRE(targetp != NULL && *targetp == NULL);
 822
 823	isc_refcount_increment(&source->refs, NULL);
 824	*targetp = source;
 825}
 826
 827static void
 828tsigkey_free(dns_tsigkey_t *key) {
 829	REQUIRE(VALID_TSIG_KEY(key));
 830
 831	key->magic = 0;
 832	dns_name_free(&key->name, key->mctx);
 833	if (algname_is_allocated(key->algorithm)) {
 834		dns_name_free(key->algorithm, key->mctx);
 835		isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t));
 836	}
 837	if (key->key != NULL)
 838		dst_key_free(&key->key);
 839	if (key->creator != NULL) {
 840		dns_name_free(key->creator, key->mctx);
 841		isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
 842	}
 843	isc_refcount_destroy(&key->refs);
 844	isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
 845}
 846
 847void
 848dns_tsigkey_detach(dns_tsigkey_t **keyp) {
 849	dns_tsigkey_t *key;
 850	unsigned int refs;
 851
 852	REQUIRE(keyp != NULL);
 853	REQUIRE(VALID_TSIG_KEY(*keyp));
 854
 855	key = *keyp;
 856	isc_refcount_decrement(&key->refs, &refs);
 857
 858	if (refs == 0)
 859		tsigkey_free(key);
 860
 861	*keyp = NULL;
 862}
 863
 864void
 865dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
 866	REQUIRE(VALID_TSIG_KEY(key));
 867	REQUIRE(key->ring != NULL);
 868
 869	RWLOCK(&key->ring->lock, isc_rwlocktype_write);
 870	remove_fromring(key);
 871	RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
 872}
 873
 874isc_result_t
 875dns_tsig_sign(dns_message_t *msg) {
 876	dns_tsigkey_t *key;
 877	dns_rdata_any_tsig_t tsig, querytsig;
 878	unsigned char data[128];
 879	isc_buffer_t databuf, sigbuf;
 880	isc_buffer_t *dynbuf;
 881	dns_name_t *owner;
 882	dns_rdata_t *rdata = NULL;
 883	dns_rdatalist_t *datalist;
 884	dns_rdataset_t *dataset;
 885	isc_region_t r;
 886	isc_stdtime_t now;
 887	isc_mem_t *mctx;
 888	dst_context_t *ctx = NULL;
 889	isc_result_t ret;
 890	unsigned char badtimedata[BADTIMELEN];
 891	unsigned int sigsize = 0;
 892	isc_boolean_t response = is_response(msg);
 893
 894	REQUIRE(msg != NULL);
 895	REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg)));
 896
 897	/*
 898	 * If this is a response, there should be a query tsig.
 899	 */
 900	if (response && msg->querytsig == NULL)
 901		return (DNS_R_EXPECTEDTSIG);
 902
 903	dynbuf = NULL;
 904
 905	mctx = msg->mctx;
 906	key = dns_message_gettsigkey(msg);
 907
 908	tsig.mctx = mctx;
 909	tsig.common.rdclass = dns_rdataclass_any;
 910	tsig.common.rdtype = dns_rdatatype_tsig;
 911	ISC_LINK_INIT(&tsig.common, link);
 912	dns_name_init(&tsig.algorithm, NULL);
 913	dns_name_clone(key->algorithm, &tsig.algorithm);
 914
 915	isc_stdtime_get(&now);
 916	tsig.timesigned = now + msg->timeadjust;
 917	tsig.fudge = DNS_TSIG_FUDGE;
 918
 919	tsig.originalid = msg->id;
 920
 921	isc_buffer_init(&databuf, data, sizeof(data));
 922
 923	if (response)
 924		tsig.error = msg->querytsigstatus;
 925	else
 926		tsig.error = dns_rcode_noerror;
 927
 928	if (tsig.error != dns_tsigerror_badtime) {
 929		tsig.otherlen = 0;
 930		tsig.other = NULL;
 931	} else {
 932		isc_buffer_t otherbuf;
 933
 934		tsig.otherlen = BADTIMELEN;
 935		tsig.other = badtimedata;
 936		isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
 937		isc_buffer_putuint48(&otherbuf, tsig.timesigned);
 938	}
 939
 940	if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
 941		unsigned char header[DNS_MESSAGE_HEADERLEN];
 942		isc_buffer_t headerbuf;
 943		isc_uint16_t digestbits;
 944
 945		ret = dst_context_create(key->key, mctx, &ctx);
 946		if (ret != ISC_R_SUCCESS)
 947			return (ret);
 948
 949		/*
 950		 * If this is a response, digest the query signature.
 951		 */
 952		if (response) {
 953			dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
 954
 955			ret = dns_rdataset_first(msg->querytsig);
 956			if (ret != ISC_R_SUCCESS)
 957				goto cleanup_context;
 958			dns_rdataset_current(msg->querytsig, &querytsigrdata);
 959			ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
 960						 NULL);
 961			if (ret != ISC_R_SUCCESS)
 962				goto cleanup_context;
 963			isc_buffer_putuint16(&databuf, querytsig.siglen);
 964			if (isc_buffer_availablelength(&databuf) <
 965			    querytsig.siglen) {
 966				ret = ISC_R_NOSPACE;
 967				goto cleanup_context;
 968			}
 969			isc_buffer_putmem(&databuf, querytsig.signature,
 970					  querytsig.siglen);
 971			isc_buffer_usedregion(&databuf, &r);
 972			ret = dst_context_adddata(ctx, &r);
 973			if (ret != ISC_R_SUCCESS)
 974				goto cleanup_context;
 975		}
 976
 977		/*
 978		 * Digest the header.
 979		 */
 980		isc_buffer_init(&headerbuf, header, sizeof(header));
 981		dns_message_renderheader(msg, &headerbuf);
 982		isc_buffer_usedregion(&headerbuf, &r);
 983		ret = dst_context_adddata(ctx, &r);
 984		if (ret != ISC_R_SUCCESS)
 985			goto cleanup_context;
 986
 987		/*
 988		 * Digest the remainder of the message.
 989		 */
 990		isc_buffer_usedregion(msg->buffer, &r);
 991		isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
 992		ret = dst_context_adddata(ctx, &r);
 993		if (ret != ISC_R_SUCCESS)
 994			goto cleanup_context;
 995
 996		if (msg->tcp_continuation == 0) {
 997			/*
 998			 * Digest the name, class, ttl, alg.
 999			 */
1000			dns_name_toregion(&key->name, &r);
1001			ret = dst_context_adddata(ctx, &r);
1002			if (ret != ISC_R_SUCCESS)
1003				goto cleanup_context;
1004
1005			isc_buffer_clear(&databuf);
1006			isc_buffer_putuint16(&databuf, dns_rdataclass_any);
1007			isc_buffer_putuint32(&databuf, 0); /* ttl */
1008			isc_buffer_usedregion(&databuf, &r);
1009			ret = dst_context_adddata(ctx, &r);
1010			if (ret != ISC_R_SUCCESS)
1011				goto cleanup_context;
1012
1013			dns_name_toregion(&tsig.algorithm, &r);
1014			ret = dst_context_adddata(ctx, &r);
1015			if (ret != ISC_R_SUCCESS)
1016				goto cleanup_context;
1017
1018		}
1019		/* Digest the timesigned and fudge */
1020		isc_buffer_clear(&databuf);
1021		if (tsig.error == dns_tsigerror_badtime) {
1022			INSIST(response);
1023			tsig.timesigned = querytsig.timesigned;
1024		}
1025		isc_buffer_putuint48(&databuf, tsig.timesigned);
1026		isc_buffer_putuint16(&databuf, tsig.fudge);
1027		isc_buffer_usedregion(&databuf, &r);
1028		ret = dst_context_adddata(ctx, &r);
1029		if (ret != ISC_R_SUCCESS)
1030			goto cleanup_context;
1031
1032		if (msg->tcp_continuation == 0) {
1033			/*
1034			 * Digest the error and other data length.
1035			 */
1036			isc_buffer_clear(&databuf);
1037			isc_buffer_putuint16(&databuf, tsig.error);
1038			isc_buffer_putuint16(&databuf, tsig.otherlen);
1039
1040			isc_buffer_usedregion(&databuf, &r);
1041			ret = dst_context_adddata(ctx, &r);
1042			if (ret != ISC_R_SUCCESS)
1043				goto cleanup_context;
1044
1045			/*
1046			 * Digest other data.
1047			 */
1048			if (tsig.otherlen > 0) {
1049				r.length = tsig.otherlen;
1050				r.base = tsig.other;
1051				ret = dst_context_adddata(ctx, &r);
1052				if (ret != ISC_R_SUCCESS)
1053					goto cleanup_context;
1054			}
1055		}
1056
1057		ret = dst_key_sigsize(key->key, &sigsize);
1058		if (ret != ISC_R_SUCCESS)
1059			goto cleanup_context;
1060		tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
1061		if (tsig.signature == NULL) {
1062			ret = ISC_R_NOMEMORY;
1063			goto cleanup_context;
1064		}
1065
1066		isc_buffer_init(&sigbuf, tsig.signature, sigsize);
1067		ret = dst_context_sign(ctx, &sigbuf);
1068		if (ret != ISC_R_SUCCESS)
1069			goto cleanup_signature;
1070		dst_context_destroy(&ctx);
1071		digestbits = dst_key_getbits(key->key);
1072		if (digestbits != 0) {
1073			unsigned int bytes = (digestbits + 1) / 8;
1074			if (response && bytes < querytsig.siglen)
1075				bytes = querytsig.siglen;
1076			if (bytes > isc_buffer_usedlength(&sigbuf))
1077				bytes = isc_buffer_usedlength(&sigbuf);
1078			tsig.siglen = bytes;
1079		} else
1080			tsig.siglen = isc_buffer_usedlength(&sigbuf);
1081	} else {
1082		tsig.siglen = 0;
1083		tsig.signature = NULL;
1084	}
1085
1086	ret = dns_message_gettemprdata(msg, &rdata);
1087	if (ret != ISC_R_SUCCESS)
1088		goto cleanup_signature;
1089	ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
1090	if (ret != ISC_R_SUCCESS)
1091		goto cleanup_rdata;
1092	ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
1093				   dns_rdatatype_tsig, &tsig, dynbuf);
1094	if (ret != ISC_R_SUCCESS)
1095		goto cleanup_dynbuf;
1096
1097	dns_message_takebuffer(msg, &dynbuf);
1098
1099	if (tsig.signature != NULL) {
1100		isc_mem_put(mctx, tsig.signature, sigsize);
1101		tsig.signature = NULL;
1102	}
1103
1104	owner = NULL;
1105	ret = dns_message_gettempname(msg, &owner);
1106	if (ret != ISC_R_SUCCESS)
1107		goto cleanup_rdata;
1108	dns_name_init(owner, NULL);
1109	ret = dns_name_dup(&key->name, msg->mctx, owner);
1110	if (ret != ISC_R_SUCCESS)
1111		goto cleanup_owner;
1112
1113	datalist = NULL;
1114	ret = dns_message_gettemprdatalist(msg, &datalist);
1115	if (ret != ISC_R_SUCCESS)
1116		goto cleanup_owner;
1117	dataset = NULL;
1118	ret = dns_message_gettemprdataset(msg, &dataset);
1119	if (ret != ISC_R_SUCCESS)
1120		goto cleanup_rdatalist;
1121	datalist->rdclass = dns_rdataclass_any;
1122	datalist->type = dns_rdatatype_tsig;
1123	datalist->covers = 0;
1124	datalist->ttl = 0;
1125	ISC_LIST_INIT(datalist->rdata);
1126	ISC_LIST_APPEND(datalist->rdata, rdata, link);
1127	dns_rdataset_init(dataset);
1128	RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
1129		      == ISC_R_SUCCESS);
1130	msg->tsig = dataset;
1131	msg->tsigname = owner;
1132
1133	/* Windows does not like the tsig name being compressed. */
1134	msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
1135
1136	return (ISC_R_SUCCESS);
1137
1138 cleanup_rdatalist:
1139	dns_message_puttemprdatalist(msg, &datalist);
1140 cleanup_owner:
1141	dns_message_puttempname(msg, &owner);
1142	goto cleanup_rdata;
1143 cleanup_dynbuf:
1144	isc_buffer_free(&dynbuf);
1145 cleanup_rdata:
1146	dns_message_puttemprdata(msg, &rdata);
1147 cleanup_signature:
1148	if (tsig.signature != NULL)
1149		isc_mem_put(mctx, tsig.signature, sigsize);
1150 cleanup_context:
1151	if (ctx != NULL)
1152		dst_context_destroy(&ctx);
1153	return (ret);
1154}
1155
1156isc_result_t
1157dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
1158		dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2)
1159{
1160	dns_rdata_any_tsig_t tsig, querytsig;
1161	isc_region_t r, source_r, header_r, sig_r;
1162	isc_buffer_t databuf;
1163	unsigned char data[32];
1164	dns_name_t *keyname;
1165	dns_rdata_t rdata = DNS_RDATA_INIT;
1166	isc_stdtime_t now;
1167	isc_result_t ret;
1168	dns_tsigkey_t *tsigkey;
1169	dst_key_t *key = NULL;
1170	unsigned char header[DNS_MESSAGE_HEADERLEN];
1171	dst_context_t *ctx = NULL;
1172	isc_mem_t *mctx;
1173	isc_uint16_t addcount, id;
1174	unsigned int siglen;
1175	unsigned int alg;
1176	isc_boolean_t response;
1177
1178	REQUIRE(source != NULL);
1179	REQUIRE(DNS_MESSAGE_VALID(msg));
1180	tsigkey = dns_message_gettsigkey(msg);
1181	response = is_response(msg);
1182
1183	REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
1184
1185	msg->verify_attempted = 1;
1186
1187	if (msg->tcp_continuation) {
1188		if (tsigkey == NULL || msg->querytsig == NULL)
1189			return (DNS_R_UNEXPECTEDTSIG);
1190		return (tsig_verify_tcp(source, msg));
1191	}
1192
1193	/*
1194	 * There should be a TSIG record...
1195	 */
1196	if (msg->tsig == NULL)
1197		return (DNS_R_EXPECTEDTSIG);
1198
1199	/*
1200	 * If this is a response and there's no key or query TSIG, there
1201	 * shouldn't be one on the response.
1202	 */
1203	if (response && (tsigkey == NULL || msg->querytsig == NULL))
1204		return (DNS_R_UNEXPECTEDTSIG);
1205
1206	mctx = msg->mctx;
1207
1208	/*
1209	 * If we're here, we know the message is well formed and contains a
1210	 * TSIG record.
1211	 */
1212
1213	keyname = msg->tsigname;
1214	ret = dns_rdataset_first(msg->tsig);
1215	if (ret != ISC_R_SUCCESS)
1216		return (ret);
1217	dns_rdataset_current(msg->tsig, &rdata);
1218	ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
1219	if (ret != ISC_R_SUCCESS)
1220		return (ret);
1221	dns_rdata_reset(&rdata);
1222	if (response) {
1223		ret = dns_rdataset_first(msg->querytsig);
1224		if (ret != ISC_R_SUCCESS)
1225			return (ret);
1226		dns_rdataset_current(msg->querytsig, &rdata);
1227		ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
1228		if (ret != ISC_R_SUCCESS)
1229			return (ret);
1230	}
1231
1232	/*
1233	 * Do the key name and algorithm match that of the query?
1234	 */
1235	if (response &&
1236	    (!dns_name_equal(keyname, &tsigkey->name) ||
1237	     !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
1238		msg->tsigstatus = dns_tsigerror_badkey;
1239		tsig_log(msg->tsigkey, 2,
1240			 "key name and algorithm do not match");
1241		return (DNS_R_TSIGVERIFYFAILURE);
1242	}
1243
1244	/*
1245	 * Get the current time.
1246	 */
1247	isc_stdtime_get(&now);
1248
1249	/*
1250	 * Find dns_tsigkey_t based on keyname.
1251	 */
1252	if (tsigkey == NULL) {
1253		ret = ISC_R_NOTFOUND;
1254		if (ring1 != NULL)
1255			ret = dns_tsigkey_find(&tsigkey, keyname,
1256					       &tsig.algorithm, ring1);
1257		if (ret == ISC_R_NOTFOUND && ring2 != NULL)
1258			ret = dns_tsigkey_find(&tsigkey, keyname,
1259					       &tsig.algorithm, ring2);
1260		if (ret != ISC_R_SUCCESS) {
1261			msg->tsigstatus = dns_tsigerror_badkey;
1262			ret = dns_tsigkey_create(keyname, &tsig.algorithm,
1263						 NULL, 0, ISC_FALSE, NULL,
1264						 now, now,
1265						 mctx, NULL, &msg->tsigkey);
1266			if (ret != ISC_R_SUCCESS)
1267				return (ret);
1268			tsig_log(msg->tsigkey, 2, "unknown key");
1269			return (DNS_R_TSIGVERIFYFAILURE);
1270		}
1271		msg->tsigkey = tsigkey;
1272	}
1273
1274	key = tsigkey->key;
1275
1276	/*
1277	 * Is the time ok?
1278	 */
1279	if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
1280		msg->tsigstatus = dns_tsigerror_badtime;
1281		tsig_log(msg->tsigkey, 2, "signature has expired");
1282		return (DNS_R_CLOCKSKEW);
1283	} else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
1284		msg->tsigstatus = dns_tsigerror_badtime;
1285		tsig_log(msg->tsigkey, 2, "signature is in the future");
1286		return (DNS_R_CLOCKSKEW);
1287	}
1288
1289	/*
1290	 * Check digest length.
1291	 */
1292	alg = dst_key_alg(key);
1293	ret = dst_key_sigsize(key, &siglen);
1294	if (ret != ISC_R_SUCCESS)
1295		return (ret);
1296	if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 ||
1297	    alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
1298	    alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) {
1299		isc_uint16_t digestbits = dst_key_getbits(key);
1300		if (tsig.siglen > siglen) {
1301			tsig_log(msg->tsigkey, 2, "signature length to big");
1302			return (DNS_R_FORMERR);
1303		}
1304		if (tsig.siglen > 0 &&
1305		    (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) {
1306			tsig_log(msg->tsigkey, 2,
1307				 "signature length below minimum");
1308			return (DNS_R_FORMERR);
1309		}
1310		if (tsig.siglen > 0 && digestbits != 0 &&
1311		    tsig.siglen < ((digestbits + 1) / 8)) {
1312			msg->tsigstatus = dns_tsigerror_badtrunc;
1313			tsig_log(msg->tsigkey, 2,
1314				 "truncated signature length too small");
1315			return (DNS_R_TSIGVERIFYFAILURE);
1316		}
1317		if (tsig.siglen > 0 && digestbits == 0 &&
1318		    tsig.siglen < siglen) {
1319			msg->tsigstatus = dns_tsigerror_badtrunc;
1320			tsig_log(msg->tsigkey, 2, "signature length too small");
1321			return (DNS_R_TSIGVERIFYFAILURE);
1322		}
1323	}
1324
1325	if (tsig.siglen > 0) {
1326		sig_r.base = tsig.signature;
1327		sig_r.length = tsig.siglen;
1328
1329		ret = dst_context_create(key, mctx, &ctx);
1330		if (ret != ISC_R_SUCCESS)
1331			return (ret);
1332
1333		if (response) {
1334			isc_buffer_init(&databuf, data, sizeof(data));
1335			isc_buffer_putuint16(&databuf, querytsig.siglen);
1336			isc_buffer_usedregion(&databuf, &r);
1337			ret = dst_context_adddata(ctx, &r);
1338			if (ret != ISC_R_SUCCESS)
1339				goto cleanup_context;
1340			if (querytsig.siglen > 0) {
1341				r.length = querytsig.siglen;
1342				r.base = querytsig.signature;
1343				ret = dst_context_adddata(ctx, &r);
1344				if (ret != ISC_R_SUCCESS)
1345					goto cleanup_context;
1346			}
1347		}
1348
1349		/*
1350		 * Extract the header.
1351		 */
1352		isc_buffer_usedregion(source, &r);
1353		memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
1354		isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1355
1356		/*
1357		 * Decrement the additional field counter.
1358		 */
1359		memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
1360		addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
1361		memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
1362
1363		/*
1364		 * Put in the original id.
1365		 */
1366		id = htons(tsig.originalid);
1367		memcpy(&header[0], &id, 2);
1368
1369		/*
1370		 * Digest the modified header.
1371		 */
1372		header_r.base = (unsigned char *) header;
1373		header_r.length = DNS_MESSAGE_HEADERLEN;
1374		ret = dst_context_adddata(ctx, &header_r);
1375		if (ret != ISC_R_SUCCESS)
1376			goto cleanup_context;
1377
1378		/*
1379		 * Digest all non-TSIG records.
1380		 */
1381		isc_buffer_usedregion(source, &source_r);
1382		r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
1383		r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
1384		ret = dst_context_adddata(ctx, &r);
1385		if (ret != ISC_R_SUCCESS)
1386			goto cleanup_context;
1387
1388		/*
1389		 * Digest the key name.
1390		 */
1391		dns_name_toregion(&tsigkey->name, &r);
1392		ret = dst_context_adddata(ctx, &r);
1393		if (ret != ISC_R_SUCCESS)
1394			goto cleanup_context;
1395
1396		isc_buffer_init(&databuf, data, sizeof(data));
1397		isc_buffer_putuint16(&databuf, tsig.common.rdclass);
1398		isc_buffer_putuint32(&databuf, msg->tsig->ttl);
1399		isc_buffer_usedregion(&databuf, &r);
1400		ret = dst_context_adddata(ctx, &r);
1401		if (ret != ISC_R_SUCCESS)
1402			goto cleanup_context;
1403
1404		/*
1405		 * Digest the key algorithm.
1406		 */
1407		dns_name_toregion(tsigkey->algorithm, &r);
1408		ret = dst_context_adddata(ctx, &r);
1409		if (ret != ISC_R_SUCCESS)
1410			goto cleanup_context;
1411
1412		isc_buffer_clear(&databuf);
1413		isc_buffer_putuint48(&databuf, tsig.timesigned);
1414		isc_buffer_putuint16(&databuf, tsig.fudge);
1415		isc_buffer_putuint16(&databuf, tsig.error);
1416		isc_buffer_putuint16(&databuf, tsig.otherlen);
1417		isc_buffer_usedregion(&databuf, &r);
1418		ret = dst_context_adddata(ctx, &r);
1419		if (ret != ISC_R_SUCCESS)
1420			goto cleanup_context;
1421
1422		if (tsig.otherlen > 0) {
1423			r.base = tsig.other;
1424			r.length = tsig.otherlen;
1425			ret = dst_context_adddata(ctx, &r);
1426			if (ret != ISC_R_SUCCESS)
1427				goto cleanup_context;
1428		}
1429
1430		ret = dst_context_verify(ctx, &sig_r);
1431		if (ret == DST_R_VERIFYFAILURE) {
1432			msg->tsigstatus = dns_tsigerror_badsig;
1433			ret = DNS_R_TSIGVERIFYFAILURE;
1434			tsig_log(msg->tsigkey, 2,
1435				 "signature failed to verify(1)");
1436			goto cleanup_context;
1437		} else if (ret != ISC_R_SUCCESS)
1438			goto cleanup_context;
1439
1440		dst_context_destroy(&ctx);
1441	} else if (tsig.error != dns_tsigerror_badsig &&
1442		   tsig.error != dns_tsigerror_badkey) {
1443		msg->tsigstatus = dns_tsigerror_badsig;
1444		tsig_log(msg->tsigkey, 2, "signature was empty");
1445		return (DNS_R_TSIGVERIFYFAILURE);
1446	}
1447
1448	msg->tsigstatus = dns_rcode_noerror;
1449
1450	if (tsig.error != dns_rcode_noerror) {
1451		if (tsig.error == dns_tsigerror_badtime)
1452			return (DNS_R_CLOCKSKEW);
1453		else
1454			return (DNS_R_TSIGERRORSET);
1455	}
1456
1457	msg->verified_sig = 1;
1458
1459	return (ISC_R_SUCCESS);
1460
1461cleanup_context:
1462	if (ctx != NULL)
1463		dst_context_destroy(&ctx);
1464
1465	return (ret);
1466}
1467
1468static isc_result_t
1469tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
1470	dns_rdata_any_tsig_t tsig, querytsig;
1471	isc_region_t r, source_r, header_r, sig_r;
1472	isc_buffer_t databuf;
1473	unsigned char data[32];
1474	dns_name_t *keyname;
1475	dns_rdata_t rdata = DNS_RDATA_INIT;
1476	isc_stdtime_t now;
1477	isc_result_t ret;
1478	dns_tsigkey_t *tsigkey;
1479	dst_key_t *key = NULL;
1480	unsigned char header[DNS_MESSAGE_HEADERLEN];
1481	isc_uint16_t addcount, id;
1482	isc_boolean_t has_tsig = ISC_FALSE;
1483	isc_mem_t *mctx;
1484
1485	REQUIRE(source != NULL);
1486	REQUIRE(msg != NULL);
1487	REQUIRE(dns_message_gettsigkey(msg) != NULL);
1488	REQUIRE(msg->tcp_continuation == 1);
1489	REQUIRE(msg->querytsig != NULL);
1490
1491	if (!is_response(msg))
1492		return (DNS_R_EXPECTEDRESPONSE);
1493
1494	mctx = msg->mctx;
1495
1496	tsigkey = dns_message_gettsigkey(msg);
1497
1498	/*
1499	 * Extract and parse the previous TSIG
1500	 */
1501	ret = dns_rdataset_first(msg->querytsig);
1502	if (ret != ISC_R_SUCCESS)
1503		return (ret);
1504	dns_rdataset_current(msg->querytsig, &rdata);
1505	ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
1506	if (ret != ISC_R_SUCCESS)
1507		return (ret);
1508	dns_rdata_reset(&rdata);
1509
1510	/*
1511	 * If there is a TSIG in this message, do some checks.
1512	 */
1513	if (msg->tsig != NULL) {
1514		has_tsig = ISC_TRUE;
1515
1516		keyname = msg->tsigname;
1517		ret = dns_rdataset_first(msg->tsig);
1518		if (ret != ISC_R_SUCCESS)
1519			goto cleanup_querystruct;
1520		dns_rdataset_current(msg->tsig, &rdata);
1521		ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
1522		if (ret != ISC_R_SUCCESS)
1523			goto cleanup_querystruct;
1524
1525		/*
1526		 * Do the key name and algorithm match that of the query?
1527		 */
1528		if (!dns_name_equal(keyname, &tsigkey->name) ||
1529		    !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) {
1530			msg->tsigstatus = dns_tsigerror_badkey;
1531			ret = DNS_R_TSIGVERIFYFAILURE;
1532			tsig_log(msg->tsigkey, 2,
1533				 "key name and algorithm do not match");
1534			goto cleanup_querystruct;
1535		}
1536
1537		/*
1538		 * Is the time ok?
1539		 */
1540		isc_stdtime_get(&now);
1541
1542		if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
1543			msg->tsigstatus = dns_tsigerror_badtime;
1544			tsig_log(msg->tsigkey, 2, "signature has expired");
1545			ret = DNS_R_CLOCKSKEW;
1546			goto cleanup_querystruct;
1547		} else if (now + msg->timeadjust <
1548			   tsig.timesigned - tsig.fudge) {
1549			msg->tsigstatus = dns_tsigerror_badtime;
1550			tsig_log(msg->tsigkey, 2,
1551				 "signature is in the future");
1552			ret = DNS_R_CLOCKSKEW;
1553			goto cleanup_querystruct;
1554		}
1555	}
1556
1557	key = tsigkey->key;
1558
1559	if (msg->tsigctx == NULL) {
1560		ret = dst_context_create(key, mctx, &msg->tsigctx);
1561		if (ret != ISC_R_SUCCESS)
1562			goto cleanup_querystruct;
1563
1564		/*
1565		 * Digest the length of the query signature
1566		 */
1567		isc_buffer_init(&databuf, data, sizeof(data));
1568		isc_buffer_putuint16(&databuf, querytsig.siglen);
1569		isc_buffer_usedregion(&databuf, &r);
1570		ret = dst_context_adddata(msg->tsigctx, &r);
1571		if (ret != ISC_R_SUCCESS)
1572			goto cleanup_context;
1573
1574		/*
1575		 * Digest the data of the query signature
1576		 */
1577		if (querytsig.siglen > 0) {
1578			r.length = querytsig.siglen;
1579			r.base = querytsig.signature;
1580			ret = dst_context_adddata(msg->tsigctx, &r);
1581			if (ret != ISC_R_SUCCESS)
1582				goto cleanup_context;
1583		}
1584	}
1585
1586	/*
1587	 * Extract the header.
1588	 */
1589	isc_buffer_usedregion(source, &r);
1590	memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
1591	isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1592
1593	/*
1594	 * Decrement the additional field counter if necessary.
1595	 */
1596	if (has_tsig) {
1597		memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
1598		addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
1599		memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
1600	}
1601
1602	/*
1603	 * Put in the original id.
1604	 */
1605	/* XXX Can TCP transfers be forwarded?  How would that work? */
1606	if (has_tsig) {
1607		id = htons(tsig.originalid);
1608		memcpy(&header[0], &id, 2);
1609	}
1610
1611	/*
1612	 * Digest the modified header.
1613	 */
1614	header_r.base = (unsigned char *) header;
1615	header_r.length = DNS_MESSAGE_HEADERLEN;
1616	ret = dst_context_adddata(msg->tsigctx, &header_r);
1617	if (ret != ISC_R_SUCCESS)
1618		goto cleanup_context;
1619
1620	/*
1621	 * Digest all non-TSIG records.
1622	 */
1623	isc_buffer_usedregion(source, &source_r);
1624	r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
1625	if (has_tsig)
1626		r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
1627	else
1628		r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
1629	ret = dst_context_adddata(msg->tsigctx, &r);
1630	if (ret != ISC_R_SUCCESS)
1631		goto cleanup_context;
1632
1633	/*
1634	 * Digest the time signed and fudge.
1635	 */
1636	if (has_tsig) {
1637		isc_buffer_init(&databuf, data, sizeof(data));
1638		isc_buffer_putuint48(&databuf, tsig.timesigned);
1639		isc_buffer_putuint16(&databuf, tsig.fudge);
1640		isc_buffer_usedregion(&databuf, &r);
1641		ret = dst_context_adddata(msg->tsigctx, &r);
1642		if (ret != ISC_R_SUCCESS)
1643			goto cleanup_context;
1644
1645		sig_r.base = tsig.signature;
1646		sig_r.length = tsig.siglen;
1647		if (tsig.siglen == 0) {
1648			if (tsig.error != dns_rcode_noerror) {
1649				if (tsig.error == dns_tsigerror_badtime)
1650					ret = DNS_R_CLOCKSKEW;
1651				else
1652					ret = DNS_R_TSIGERRORSET;
1653			} else {
1654				tsig_log(msg->tsigkey, 2,
1655					 "signature is empty");
1656				ret = DNS_R_TSIGVERIFYFAILURE;
1657			}
1658			goto cleanup_context;
1659		}
1660
1661		ret = dst_context_verify(msg->tsigctx, &sig_r);
1662		if (ret == DST_R_VERIFYFAILURE) {
1663			msg->tsigstatus = dns_tsigerror_badsig;
1664			tsig_log(msg->tsigkey, 2,
1665				 "signature failed to verify(2)");
1666			ret = DNS_R_TSIGVERIFYFAILURE;
1667			goto cleanup_context;
1668		}
1669		else if (ret != ISC_R_SUCCESS)
1670			goto cleanup_context;
1671
1672		dst_context_destroy(&msg->tsigctx);
1673	}
1674
1675	msg->tsigstatus = dns_rcode_noerror;
1676	return (ISC_R_SUCCESS);
1677
1678 cleanup_context:
1679	dst_context_destroy(&msg->tsigctx);
1680
1681 cleanup_querystruct:
1682	dns_rdata_freestruct(&querytsig);
1683
1684	return (ret);
1685
1686}
1687
1688isc_result_t
1689dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
1690		 dns_name_t *algorithm, dns_tsig_keyring_t *ring)
1691{
1692	dns_tsigkey_t *key;
1693	isc_stdtime_t now;
1694	isc_result_t result;
1695
1696	REQUIRE(tsigkey != NULL);
1697	REQUIRE(*tsigkey == NULL);
1698	REQUIRE(name != NULL);
1699	REQUIRE(ring != NULL);
1700
1701	RWLOCK(&ring->lock, isc_rwlocktype_write);
1702	cleanup_ring(ring);
1703	RWUNLOCK(&ring->lock, isc_rwlocktype_write);
1704
1705	isc_stdtime_get(&now);
1706	RWLOCK(&ring->lock, isc_rwlocktype_read);
1707	key = NULL;
1708	result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
1709	if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
1710		RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1711		return (ISC_R_NOTFOUND);
1712	}
1713	if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
1714		RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1715		return (ISC_R_NOTFOUND);
1716	}
1717	if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
1718		/*
1719		 * The key has expired.
1720		 */
1721		RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1722		RWLOCK(&ring->lock, isc_rwlocktype_write);
1723		remove_fromring(key);
1724		RWUNLOCK(&ring->lock, isc_rwlocktype_write);
1725		return (ISC_R_NOTFOUND);
1726	}
1727#if 0
1728	/*
1729	 * MPAXXX We really should look at the inception time.
1730	 */
1731	if (key->inception != key->expire &&
1732	    isc_serial_lt(key->inception, now)) {
1733		RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1734		adjust_lru(key);
1735		return (ISC_R_NOTFOUND);
1736	}
1737#endif
1738	isc_refcount_increment(&key->refs, NULL);
1739	RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1740	adjust_lru(key);
1741	*tsigkey = key;
1742	return (ISC_R_SUCCESS);
1743}
1744
1745static void
1746free_tsignode(void *node, void *_unused) {
1747	dns_tsigkey_t *key;
1748
1749	UNUSED(_unused);
1750
1751	REQUIRE(node != NULL);
1752
1753	key = node;
1754	dns_tsigkey_detach(&key);
1755}
1756
1757isc_result_t
1758dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
1759	isc_result_t result;
1760	dns_tsig_keyring_t *ring;
1761
1762	REQUIRE(mctx != NULL);
1763	REQUIRE(ringp != NULL);
1764	REQUIRE(*ringp == NULL);
1765
1766	ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
1767	if (ring == NULL)
1768		return (ISC_R_NOMEMORY);
1769
1770	result = isc_rwlock_init(&ring->lock, 0, 0);
1771	if (result != ISC_R_SUCCESS) {
1772		isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
1773		return (result);
1774	}
1775
1776	ring->keys = NULL;
1777	result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
1778	if (result != ISC_R_SUCCESS) {
1779		isc_rwlock_destroy(&ring->lock);
1780		isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
1781		return (result);
1782	}
1783
1784	ring->writecount = 0;
1785	ring->mctx = NULL;
1786	ring->generated = 0;
1787	ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
1788	ISC_LIST_INIT(ring->lru);
1789	isc_mem_attach(mctx, &ring->mctx);
1790	ring->references = 1;
1791
1792	*ringp = ring;
1793	return (ISC_R_SUCCESS);
1794}
1795
1796isc_result_t
1797dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
1798		    dns_tsigkey_t *tkey)
1799{
1800	isc_result_t result;
1801
1802	result = keyring_add(ring, name, tkey);
1803	if (result == ISC_R_SUCCESS)
1804		isc_refcount_increment(&tkey->refs, NULL);
1805
1806	return (result);
1807}
1808
1809void
1810dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
1811{
1812	REQUIRE(source != NULL);
1813	REQUIRE(target != NULL && *target == NULL);
1814
1815	RWLOCK(&source->lock, isc_rwlocktype_write);
1816	INSIST(source->references > 0);
1817	source->references++;
1818	INSIST(source->references > 0);
1819	*target = source;
1820	RWUNLOCK(&source->lock, isc_rwlocktype_write);
1821}
1822
1823void
1824dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
1825	dns_tsig_keyring_t *ring;
1826	unsigned int references;
1827
1828	REQUIRE(ringp != NULL);
1829	REQUIRE(*ringp != NULL);
1830
1831	ring = *ringp;
1832	*ringp = NULL;
1833
1834	RWLOCK(&ring->lock, isc_rwlocktype_write);
1835	INSIST(ring->references > 0);
1836	ring->references--;
1837	references = ring->references;
1838	RWUNLOCK(&ring->lock, isc_rwlocktype_write);
1839
1840	if (references == 0)
1841		destroyring(ring);
1842}
1843
1844void
1845dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) {
1846	isc_stdtime_t now;
1847	isc_result_t result;
1848
1849	isc_stdtime_get(&now);
1850	do {
1851		result = restore_key(ring, now, fp);
1852		if (result == IS

Large files files are truncated, but you can click here to view the full file