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