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