2 * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
19 * $Id: tsig.c,v 1.147.10.1 2011-03-21 19:53:34 each Exp $
25 #include <isc/buffer.h>
27 #include <isc/print.h>
28 #include <isc/refcount.h>
29 #include <isc/serial.h>
30 #include <isc/string.h> /* Required for HP/UX (and others?) */
34 #include <dns/keyvalues.h>
36 #include <dns/message.h>
37 #include <dns/fixedname.h>
39 #include <dns/rdata.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
42 #include <dns/rdatastruct.h>
43 #include <dns/result.h>
46 #include <dst/result.h>
48 #define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G')
49 #define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)
51 #ifndef DNS_TSIG_MAXGENERATEDKEYS
52 #define DNS_TSIG_MAXGENERATEDKEYS 4096
55 #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
56 #define algname_is_allocated(algname) \
57 ((algname) != dns_tsig_hmacmd5_name && \
58 (algname) != dns_tsig_hmacsha1_name && \
59 (algname) != dns_tsig_hmacsha224_name && \
60 (algname) != dns_tsig_hmacsha256_name && \
61 (algname) != dns_tsig_hmacsha384_name && \
62 (algname) != dns_tsig_hmacsha512_name && \
63 (algname) != dns_tsig_gssapi_name && \
64 (algname) != dns_tsig_gssapims_name)
68 static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";
69 static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };
71 static dns_name_t hmacmd5 = {
74 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
75 hmacmd5_offsets, NULL,
76 {(void *)-1, (void *)-1},
80 dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
82 static unsigned char gsstsig_ndata[] = "\010gss-tsig";
83 static unsigned char gsstsig_offsets[] = { 0, 9 };
84 static dns_name_t gsstsig = {
87 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
88 gsstsig_offsets, NULL,
89 {(void *)-1, (void *)-1},
92 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
95 * Since Microsoft doesn't follow its own standard, we will use this
96 * alternate name as a second guess.
98 static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
99 static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
100 static dns_name_t gsstsigms = {
102 gsstsigms_ndata, 19, 4,
103 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
104 gsstsigms_offsets, NULL,
105 {(void *)-1, (void *)-1},
108 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
110 static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
111 static unsigned char hmacsha1_offsets[] = { 0, 10 };
113 static dns_name_t hmacsha1 = {
115 hmacsha1_ndata, 11, 2,
116 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
117 hmacsha1_offsets, NULL,
118 {(void *)-1, (void *)-1},
122 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
124 static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
125 static unsigned char hmacsha224_offsets[] = { 0, 12 };
127 static dns_name_t hmacsha224 = {
129 hmacsha224_ndata, 13, 2,
130 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
131 hmacsha224_offsets, NULL,
132 {(void *)-1, (void *)-1},
136 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
138 static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
139 static unsigned char hmacsha256_offsets[] = { 0, 12 };
141 static dns_name_t hmacsha256 = {
143 hmacsha256_ndata, 13, 2,
144 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
145 hmacsha256_offsets, NULL,
146 {(void *)-1, (void *)-1},
150 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
152 static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
153 static unsigned char hmacsha384_offsets[] = { 0, 12 };
155 static dns_name_t hmacsha384 = {
157 hmacsha384_ndata, 13, 2,
158 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
159 hmacsha384_offsets, NULL,
160 {(void *)-1, (void *)-1},
164 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
166 static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
167 static unsigned char hmacsha512_offsets[] = { 0, 12 };
169 static dns_name_t hmacsha512 = {
171 hmacsha512_ndata, 13, 2,
172 DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
173 hmacsha512_offsets, NULL,
174 {(void *)-1, (void *)-1},
178 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
181 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
184 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
185 ISC_FORMAT_PRINTF(3, 4);
188 cleanup_ring(dns_tsig_keyring_t *ring);
190 tsigkey_free(dns_tsigkey_t *key);
193 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
196 char namestr[DNS_NAME_FORMATSIZE];
197 char creatorstr[DNS_NAME_FORMATSIZE];
199 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
202 dns_name_format(&key->name, namestr, sizeof(namestr));
204 strcpy(namestr, "<null>");
206 if (key != NULL && key->generated && key->creator)
207 dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
209 strcpy(creatorstr, "<null>");
212 vsnprintf(message, sizeof(message), fmt, ap);
214 if (key != NULL && key->generated)
215 isc_log_write(dns_lctx,
216 DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
217 level, "tsig key '%s' (%s): %s",
218 namestr, creatorstr, message);
220 isc_log_write(dns_lctx,
221 DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
222 level, "tsig key '%s': %s", namestr, message);
226 remove_fromring(dns_tsigkey_t *tkey) {
227 if (tkey->generated) {
228 ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
229 tkey->ring->generated--;
231 (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
235 adjust_lru(dns_tsigkey_t *tkey) {
236 if (tkey->generated) {
237 RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
239 * We may have been removed from the LRU list between
240 * removing the read lock and aquiring the write lock.
242 if (ISC_LINK_LINKED(tkey, link)) {
243 ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
244 ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
246 RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
251 * A supplemental routine just to add a key to ring. Note that reference
252 * counter should be counted separately because we may be adding the key
253 * as part of creation of the key, in which case the reference counter was
254 * already initialized. Also note we don't need RWLOCK for the reference
255 * counter: it's protected by a separate lock.
258 keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
263 RWLOCK(&ring->lock, isc_rwlocktype_write);
267 * Do on the fly cleaning. Find some nodes we might not
268 * want around any more.
270 if (ring->writecount > 10) {
272 ring->writecount = 0;
275 result = dns_rbt_addname(ring->keys, name, tkey);
276 if (tkey->generated) {
278 * Add the new key to the LRU list and remove the least
279 * recently used key if there are too many keys on the list.
281 ISC_LIST_INITANDAPPEND(ring->lru, tkey, link);
282 if (ring->generated++ > ring->maxgenerated)
283 remove_fromring(ISC_LIST_HEAD(ring->lru));
285 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
291 dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
292 dst_key_t *dstkey, isc_boolean_t generated,
293 dns_name_t *creator, isc_stdtime_t inception,
294 isc_stdtime_t expire, isc_mem_t *mctx,
295 dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
299 unsigned int refs = 0;
301 REQUIRE(key == NULL || *key == NULL);
302 REQUIRE(name != NULL);
303 REQUIRE(algorithm != NULL);
304 REQUIRE(mctx != NULL);
305 REQUIRE(key != NULL || ring != NULL);
307 tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
309 return (ISC_R_NOMEMORY);
311 dns_name_init(&tkey->name, NULL);
312 ret = dns_name_dup(name, mctx, &tkey->name);
313 if (ret != ISC_R_SUCCESS)
315 (void)dns_name_downcase(&tkey->name, &tkey->name, NULL);
317 if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
318 tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
319 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
323 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
324 tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
325 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
329 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
330 tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
331 if (dstkey != NULL &&
332 dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
336 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
337 tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
338 if (dstkey != NULL &&
339 dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
343 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
344 tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
345 if (dstkey != NULL &&
346 dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
350 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
351 tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
352 if (dstkey != NULL &&
353 dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
357 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
358 tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
359 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
363 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
364 tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
365 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
370 if (dstkey != NULL) {
374 tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
375 if (tkey->algorithm == NULL) {
376 ret = ISC_R_NOMEMORY;
379 dns_name_init(tkey->algorithm, NULL);
380 ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
381 if (ret != ISC_R_SUCCESS)
382 goto cleanup_algorithm;
383 (void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
387 if (creator != NULL) {
388 tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
389 if (tkey->creator == NULL) {
390 ret = ISC_R_NOMEMORY;
391 goto cleanup_algorithm;
393 dns_name_init(tkey->creator, NULL);
394 ret = dns_name_dup(creator, mctx, tkey->creator);
395 if (ret != ISC_R_SUCCESS) {
396 isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
397 goto cleanup_algorithm;
400 tkey->creator = NULL;
404 dst_key_attach(dstkey, &tkey->key);
411 ret = isc_refcount_init(&tkey->refs, refs);
412 if (ret != ISC_R_SUCCESS)
413 goto cleanup_creator;
415 tkey->generated = generated;
416 tkey->inception = inception;
417 tkey->expire = expire;
419 isc_mem_attach(mctx, &tkey->mctx);
421 tkey->magic = TSIG_MAGIC;
424 ret = keyring_add(ring, name, tkey);
425 if (ret != ISC_R_SUCCESS)
430 * Ignore this if it's a GSS key, since the key size is meaningless.
432 if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
433 !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
434 !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
435 char namestr[DNS_NAME_FORMATSIZE];
436 dns_name_format(name, namestr, sizeof(namestr));
437 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
438 DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
439 "the key '%s' is too short to be secure",
446 return (ISC_R_SUCCESS);
451 isc_refcount_decrement(&tkey->refs, NULL);
452 isc_refcount_destroy(&tkey->refs);
454 if (tkey->key != NULL)
455 dst_key_free(&tkey->key);
456 if (tkey->creator != NULL) {
457 dns_name_free(tkey->creator, mctx);
458 isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
461 if (algname_is_allocated(tkey->algorithm)) {
462 if (dns_name_dynamic(tkey->algorithm))
463 dns_name_free(tkey->algorithm, mctx);
464 isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
467 dns_name_free(&tkey->name, mctx);
469 isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));
475 * Find a few nodes to destroy if possible.
478 cleanup_ring(dns_tsig_keyring_t *ring)
481 dns_rbtnodechain_t chain;
482 dns_name_t foundname;
483 dns_fixedname_t fixedorigin;
490 * Start up a new iterator each time.
492 isc_stdtime_get(&now);
493 dns_name_init(&foundname, NULL);
494 dns_fixedname_init(&fixedorigin);
495 origin = dns_fixedname_name(&fixedorigin);
498 dns_rbtnodechain_init(&chain, ring->mctx);
499 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
501 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
502 dns_rbtnodechain_invalidate(&chain);
508 dns_rbtnodechain_current(&chain, &foundname, origin, &node);
512 && isc_refcount_current(&tkey->refs) == 1
513 && tkey->inception != tkey->expire
514 && tkey->expire < now) {
515 tsig_log(tkey, 2, "tsig expire: deleting");
517 dns_rbtnodechain_invalidate(&chain);
518 remove_fromring(tkey);
522 result = dns_rbtnodechain_next(&chain, &foundname,
524 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
525 dns_rbtnodechain_invalidate(&chain);
532 destroyring(dns_tsig_keyring_t *ring) {
533 dns_rbt_destroy(&ring->keys);
534 isc_rwlock_destroy(&ring->lock);
535 isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t));
539 dst_alg_fromname(dns_name_t *algorithm) {
540 if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
541 return (DST_ALG_HMACMD5);
542 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
543 return (DST_ALG_HMACSHA1);
544 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
545 return (DST_ALG_HMACSHA224);
546 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
547 return (DST_ALG_HMACSHA256);
548 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
549 return (DST_ALG_HMACSHA384);
550 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
551 return (DST_ALG_HMACSHA512);
552 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
553 return (DST_ALG_GSSAPI);
554 } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
555 return (DST_ALG_GSSAPI);
561 restore_key(dns_tsig_keyring_t *ring, isc_stdtime_t now, FILE *fp) {
562 dst_key_t *dstkey = NULL;
564 char creatorstr[1024];
565 char algorithmstr[1024];
567 unsigned int inception, expire;
570 dns_name_t *name, *creator, *algorithm;
571 dns_fixedname_t fname, fcreator, falgorithm;
575 n = fscanf(fp, "%1023s %1023s %u %u %1023s %4095s\n", namestr,
576 creatorstr, &inception, &expire, algorithmstr, keystr);
578 return (ISC_R_NOMORE);
580 return (ISC_R_FAILURE);
582 if (isc_serial_lt(expire, now))
583 return (DNS_R_EXPIRED);
585 dns_fixedname_init(&fname);
586 name = dns_fixedname_name(&fname);
587 isc_buffer_init(&b, namestr, strlen(namestr));
588 isc_buffer_add(&b, strlen(namestr));
589 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
590 if (result != ISC_R_SUCCESS)
593 dns_fixedname_init(&fcreator);
594 creator = dns_fixedname_name(&fcreator);
595 isc_buffer_init(&b, creatorstr, strlen(creatorstr));
596 isc_buffer_add(&b, strlen(creatorstr));
597 result = dns_name_fromtext(creator, &b, dns_rootname, 0, NULL);
598 if (result != ISC_R_SUCCESS)
601 dns_fixedname_init(&falgorithm);
602 algorithm = dns_fixedname_name(&falgorithm);
603 isc_buffer_init(&b, algorithmstr, strlen(algorithmstr));
604 isc_buffer_add(&b, strlen(algorithmstr));
605 result = dns_name_fromtext(algorithm, &b, dns_rootname, 0, NULL);
606 if (result != ISC_R_SUCCESS)
609 dstalg = dst_alg_fromname(algorithm);
611 return (DNS_R_BADALG);
613 result = dst_key_restore(name, dstalg, DNS_KEYOWNER_ENTITY,
614 DNS_KEYPROTO_DNSSEC, dns_rdataclass_in,
615 ring->mctx, keystr, &dstkey);
616 if (result != ISC_R_SUCCESS)
619 result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
620 ISC_TRUE, creator, inception,
621 expire, ring->mctx, ring, NULL);
623 dst_key_free(&dstkey);
628 dump_key(dns_tsigkey_t *tkey, FILE *fp)
632 char namestr[DNS_NAME_FORMATSIZE];
633 char creatorstr[DNS_NAME_FORMATSIZE];
634 char algorithmstr[DNS_NAME_FORMATSIZE];
637 dns_name_format(&tkey->name, namestr, sizeof(namestr));
638 dns_name_format(tkey->creator, creatorstr, sizeof(creatorstr));
639 dns_name_format(tkey->algorithm, algorithmstr, sizeof(algorithmstr));
640 result = dst_key_dump(tkey->key, tkey->mctx, &buffer, &length);
641 if (result == ISC_R_SUCCESS)
642 fprintf(fp, "%s %s %u %u %s %.*s\n", namestr, creatorstr,
643 tkey->inception, tkey->expire, algorithmstr,
646 isc_mem_put(tkey->mctx, buffer, length);
650 dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t **ringp, FILE *fp) {
652 dns_rbtnodechain_t chain;
653 dns_name_t foundname;
654 dns_fixedname_t fixedorigin;
659 dns_tsig_keyring_t *ring;
660 unsigned int references;
662 REQUIRE(ringp != NULL && *ringp != NULL);
667 RWLOCK(&ring->lock, isc_rwlocktype_write);
668 INSIST(ring->references > 0);
670 references = ring->references;
671 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
674 return (DNS_R_CONTINUE);
676 isc_stdtime_get(&now);
677 dns_name_init(&foundname, NULL);
678 dns_fixedname_init(&fixedorigin);
679 origin = dns_fixedname_name(&fixedorigin);
680 dns_rbtnodechain_init(&chain, ring->mctx);
681 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
683 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
684 dns_rbtnodechain_invalidate(&chain);
690 dns_rbtnodechain_current(&chain, &foundname, origin, &node);
692 if (tkey != NULL && tkey->generated && tkey->expire >= now)
694 result = dns_rbtnodechain_next(&chain, &foundname,
696 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
697 dns_rbtnodechain_invalidate(&chain);
698 if (result == ISC_R_NOMORE)
699 result = ISC_R_SUCCESS;
710 dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
711 unsigned char *secret, int length, isc_boolean_t generated,
712 dns_name_t *creator, isc_stdtime_t inception,
713 isc_stdtime_t expire, isc_mem_t *mctx,
714 dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
716 dst_key_t *dstkey = NULL;
719 REQUIRE(length >= 0);
721 REQUIRE(secret != NULL);
723 if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
724 if (secret != NULL) {
727 isc_buffer_init(&b, secret, length);
728 isc_buffer_add(&b, length);
729 result = dst_key_frombuffer(name, DST_ALG_HMACMD5,
734 if (result != ISC_R_SUCCESS)
737 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
738 if (secret != NULL) {
741 isc_buffer_init(&b, secret, length);
742 isc_buffer_add(&b, length);
743 result = dst_key_frombuffer(name, DST_ALG_HMACSHA1,
748 if (result != ISC_R_SUCCESS)
751 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
752 if (secret != NULL) {
755 isc_buffer_init(&b, secret, length);
756 isc_buffer_add(&b, length);
757 result = dst_key_frombuffer(name, DST_ALG_HMACSHA224,
762 if (result != ISC_R_SUCCESS)
765 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
766 if (secret != NULL) {
769 isc_buffer_init(&b, secret, length);
770 isc_buffer_add(&b, length);
771 result = dst_key_frombuffer(name, DST_ALG_HMACSHA256,
776 if (result != ISC_R_SUCCESS)
779 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
780 if (secret != NULL) {
783 isc_buffer_init(&b, secret, length);
784 isc_buffer_add(&b, length);
785 result = dst_key_frombuffer(name, DST_ALG_HMACSHA384,
790 if (result != ISC_R_SUCCESS)
793 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
794 if (secret != NULL) {
797 isc_buffer_init(&b, secret, length);
798 isc_buffer_add(&b, length);
799 result = dst_key_frombuffer(name, DST_ALG_HMACSHA512,
804 if (result != ISC_R_SUCCESS)
807 } else if (length > 0)
808 return (DNS_R_BADALG);
810 result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
812 inception, expire, mctx, ring, key);
814 dst_key_free(&dstkey);
819 dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
820 REQUIRE(VALID_TSIG_KEY(source));
821 REQUIRE(targetp != NULL && *targetp == NULL);
823 isc_refcount_increment(&source->refs, NULL);
828 tsigkey_free(dns_tsigkey_t *key) {
829 REQUIRE(VALID_TSIG_KEY(key));
832 dns_name_free(&key->name, key->mctx);
833 if (algname_is_allocated(key->algorithm)) {
834 dns_name_free(key->algorithm, key->mctx);
835 isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t));
837 if (key->key != NULL)
838 dst_key_free(&key->key);
839 if (key->creator != NULL) {
840 dns_name_free(key->creator, key->mctx);
841 isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
843 isc_refcount_destroy(&key->refs);
844 isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
848 dns_tsigkey_detach(dns_tsigkey_t **keyp) {
852 REQUIRE(keyp != NULL);
853 REQUIRE(VALID_TSIG_KEY(*keyp));
856 isc_refcount_decrement(&key->refs, &refs);
865 dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
866 REQUIRE(VALID_TSIG_KEY(key));
867 REQUIRE(key->ring != NULL);
869 RWLOCK(&key->ring->lock, isc_rwlocktype_write);
870 remove_fromring(key);
871 RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
875 dns_tsig_sign(dns_message_t *msg) {
877 dns_rdata_any_tsig_t tsig, querytsig;
878 unsigned char data[128];
879 isc_buffer_t databuf, sigbuf;
880 isc_buffer_t *dynbuf;
882 dns_rdata_t *rdata = NULL;
883 dns_rdatalist_t *datalist;
884 dns_rdataset_t *dataset;
888 dst_context_t *ctx = NULL;
890 unsigned char badtimedata[BADTIMELEN];
891 unsigned int sigsize = 0;
893 REQUIRE(msg != NULL);
894 REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg)));
897 * If this is a response, there should be a query tsig.
899 if (is_response(msg) && msg->querytsig == NULL)
900 return (DNS_R_EXPECTEDTSIG);
905 key = dns_message_gettsigkey(msg);
908 tsig.common.rdclass = dns_rdataclass_any;
909 tsig.common.rdtype = dns_rdatatype_tsig;
910 ISC_LINK_INIT(&tsig.common, link);
911 dns_name_init(&tsig.algorithm, NULL);
912 dns_name_clone(key->algorithm, &tsig.algorithm);
914 isc_stdtime_get(&now);
915 tsig.timesigned = now + msg->timeadjust;
916 tsig.fudge = DNS_TSIG_FUDGE;
918 tsig.originalid = msg->id;
920 isc_buffer_init(&databuf, data, sizeof(data));
922 if (is_response(msg))
923 tsig.error = msg->querytsigstatus;
925 tsig.error = dns_rcode_noerror;
927 if (tsig.error != dns_tsigerror_badtime) {
931 isc_buffer_t otherbuf;
933 tsig.otherlen = BADTIMELEN;
934 tsig.other = badtimedata;
935 isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
936 isc_buffer_putuint48(&otherbuf, tsig.timesigned);
939 if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
940 unsigned char header[DNS_MESSAGE_HEADERLEN];
941 isc_buffer_t headerbuf;
942 isc_uint16_t digestbits;
944 ret = dst_context_create(key->key, mctx, &ctx);
945 if (ret != ISC_R_SUCCESS)
949 * If this is a response, digest the query signature.
951 if (is_response(msg)) {
952 dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
954 ret = dns_rdataset_first(msg->querytsig);
955 if (ret != ISC_R_SUCCESS)
956 goto cleanup_context;
957 dns_rdataset_current(msg->querytsig, &querytsigrdata);
958 ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
960 if (ret != ISC_R_SUCCESS)
961 goto cleanup_context;
962 isc_buffer_putuint16(&databuf, querytsig.siglen);
963 if (isc_buffer_availablelength(&databuf) <
966 goto cleanup_context;
968 isc_buffer_putmem(&databuf, querytsig.signature,
970 isc_buffer_usedregion(&databuf, &r);
971 ret = dst_context_adddata(ctx, &r);
972 if (ret != ISC_R_SUCCESS)
973 goto cleanup_context;
979 isc_buffer_init(&headerbuf, header, sizeof(header));
980 dns_message_renderheader(msg, &headerbuf);
981 isc_buffer_usedregion(&headerbuf, &r);
982 ret = dst_context_adddata(ctx, &r);
983 if (ret != ISC_R_SUCCESS)
984 goto cleanup_context;
987 * Digest the remainder of the message.
989 isc_buffer_usedregion(msg->buffer, &r);
990 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
991 ret = dst_context_adddata(ctx, &r);
992 if (ret != ISC_R_SUCCESS)
993 goto cleanup_context;
995 if (msg->tcp_continuation == 0) {
997 * Digest the name, class, ttl, alg.
999 dns_name_toregion(&key->name, &r);
1000 ret = dst_context_adddata(ctx, &r);
1001 if (ret != ISC_R_SUCCESS)
1002 goto cleanup_context;
1004 isc_buffer_clear(&databuf);
1005 isc_buffer_putuint16(&databuf, dns_rdataclass_any);
1006 isc_buffer_putuint32(&databuf, 0); /* ttl */
1007 isc_buffer_usedregion(&databuf, &r);
1008 ret = dst_context_adddata(ctx, &r);
1009 if (ret != ISC_R_SUCCESS)
1010 goto cleanup_context;
1012 dns_name_toregion(&tsig.algorithm, &r);
1013 ret = dst_context_adddata(ctx, &r);
1014 if (ret != ISC_R_SUCCESS)
1015 goto cleanup_context;
1018 /* Digest the timesigned and fudge */
1019 isc_buffer_clear(&databuf);
1020 if (tsig.error == dns_tsigerror_badtime)
1021 tsig.timesigned = querytsig.timesigned;
1022 isc_buffer_putuint48(&databuf, tsig.timesigned);
1023 isc_buffer_putuint16(&databuf, tsig.fudge);
1024 isc_buffer_usedregion(&databuf, &r);
1025 ret = dst_context_adddata(ctx, &r);
1026 if (ret != ISC_R_SUCCESS)
1027 goto cleanup_context;
1029 if (msg->tcp_continuation == 0) {
1031 * Digest the error and other data length.
1033 isc_buffer_clear(&databuf);
1034 isc_buffer_putuint16(&databuf, tsig.error);
1035 isc_buffer_putuint16(&databuf, tsig.otherlen);
1037 isc_buffer_usedregion(&databuf, &r);
1038 ret = dst_context_adddata(ctx, &r);
1039 if (ret != ISC_R_SUCCESS)
1040 goto cleanup_context;
1043 * Digest the error and other data.
1045 if (tsig.otherlen > 0) {
1046 r.length = tsig.otherlen;
1047 r.base = tsig.other;
1048 ret = dst_context_adddata(ctx, &r);
1049 if (ret != ISC_R_SUCCESS)
1050 goto cleanup_context;
1054 ret = dst_key_sigsize(key->key, &sigsize);
1055 if (ret != ISC_R_SUCCESS)
1056 goto cleanup_context;
1057 tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
1058 if (tsig.signature == NULL) {
1059 ret = ISC_R_NOMEMORY;
1060 goto cleanup_context;
1063 isc_buffer_init(&sigbuf, tsig.signature, sigsize);
1064 ret = dst_context_sign(ctx, &sigbuf);
1065 if (ret != ISC_R_SUCCESS)
1066 goto cleanup_signature;
1067 dst_context_destroy(&ctx);
1068 digestbits = dst_key_getbits(key->key);
1069 if (digestbits != 0) {
1070 unsigned int bytes = (digestbits + 1) / 8;
1071 if (is_response(msg) && bytes < querytsig.siglen)
1072 bytes = querytsig.siglen;
1073 if (bytes > isc_buffer_usedlength(&sigbuf))
1074 bytes = isc_buffer_usedlength(&sigbuf);
1075 tsig.siglen = bytes;
1077 tsig.siglen = isc_buffer_usedlength(&sigbuf);
1080 tsig.signature = NULL;
1083 ret = dns_message_gettemprdata(msg, &rdata);
1084 if (ret != ISC_R_SUCCESS)
1085 goto cleanup_signature;
1086 ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
1087 if (ret != ISC_R_SUCCESS)
1089 ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
1090 dns_rdatatype_tsig, &tsig, dynbuf);
1091 if (ret != ISC_R_SUCCESS)
1092 goto cleanup_dynbuf;
1094 dns_message_takebuffer(msg, &dynbuf);
1096 if (tsig.signature != NULL) {
1097 isc_mem_put(mctx, tsig.signature, sigsize);
1098 tsig.signature = NULL;
1102 ret = dns_message_gettempname(msg, &owner);
1103 if (ret != ISC_R_SUCCESS)
1105 dns_name_init(owner, NULL);
1106 ret = dns_name_dup(&key->name, msg->mctx, owner);
1107 if (ret != ISC_R_SUCCESS)
1111 ret = dns_message_gettemprdatalist(msg, &datalist);
1112 if (ret != ISC_R_SUCCESS)
1115 ret = dns_message_gettemprdataset(msg, &dataset);
1116 if (ret != ISC_R_SUCCESS)
1117 goto cleanup_rdatalist;
1118 datalist->rdclass = dns_rdataclass_any;
1119 datalist->type = dns_rdatatype_tsig;
1120 datalist->covers = 0;
1122 ISC_LIST_INIT(datalist->rdata);
1123 ISC_LIST_APPEND(datalist->rdata, rdata, link);
1124 dns_rdataset_init(dataset);
1125 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
1127 msg->tsig = dataset;
1128 msg->tsigname = owner;
1130 /* Windows does not like the tsig name being compressed. */
1131 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
1133 return (ISC_R_SUCCESS);
1136 dns_message_puttemprdatalist(msg, &datalist);
1138 dns_message_puttempname(msg, &owner);
1141 isc_buffer_free(&dynbuf);
1143 dns_message_puttemprdata(msg, &rdata);
1145 if (tsig.signature != NULL)
1146 isc_mem_put(mctx, tsig.signature, sigsize);
1149 dst_context_destroy(&ctx);
1154 dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
1155 dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2)
1157 dns_rdata_any_tsig_t tsig, querytsig;
1158 isc_region_t r, source_r, header_r, sig_r;
1159 isc_buffer_t databuf;
1160 unsigned char data[32];
1161 dns_name_t *keyname;
1162 dns_rdata_t rdata = DNS_RDATA_INIT;
1165 dns_tsigkey_t *tsigkey;
1166 dst_key_t *key = NULL;
1167 unsigned char header[DNS_MESSAGE_HEADERLEN];
1168 dst_context_t *ctx = NULL;
1170 isc_uint16_t addcount, id;
1171 unsigned int siglen;
1174 REQUIRE(source != NULL);
1175 REQUIRE(DNS_MESSAGE_VALID(msg));
1176 tsigkey = dns_message_gettsigkey(msg);
1178 REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
1180 msg->verify_attempted = 1;
1182 if (msg->tcp_continuation) {
1183 if (tsigkey == NULL || msg->querytsig == NULL)
1184 return (DNS_R_UNEXPECTEDTSIG);
1185 return (tsig_verify_tcp(source, msg));
1189 * There should be a TSIG record...
1191 if (msg->tsig == NULL)
1192 return (DNS_R_EXPECTEDTSIG);
1195 * If this is a response and there's no key or query TSIG, there
1196 * shouldn't be one on the response.
1198 if (is_response(msg) &&
1199 (tsigkey == NULL || msg->querytsig == NULL))
1200 return (DNS_R_UNEXPECTEDTSIG);
1205 * If we're here, we know the message is well formed and contains a
1209 keyname = msg->tsigname;
1210 ret = dns_rdataset_first(msg->tsig);
1211 if (ret != ISC_R_SUCCESS)
1213 dns_rdataset_current(msg->tsig, &rdata);
1214 ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
1215 if (ret != ISC_R_SUCCESS)
1217 dns_rdata_reset(&rdata);
1218 if (is_response(msg)) {
1219 ret = dns_rdataset_first(msg->querytsig);
1220 if (ret != ISC_R_SUCCESS)
1222 dns_rdataset_current(msg->querytsig, &rdata);
1223 ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
1224 if (ret != ISC_R_SUCCESS)
1229 * Do the key name and algorithm match that of the query?
1231 if (is_response(msg) &&
1232 (!dns_name_equal(keyname, &tsigkey->name) ||
1233 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
1234 msg->tsigstatus = dns_tsigerror_badkey;
1235 tsig_log(msg->tsigkey, 2,
1236 "key name and algorithm do not match");
1237 return (DNS_R_TSIGVERIFYFAILURE);
1241 * Get the current time.
1243 isc_stdtime_get(&now);
1246 * Find dns_tsigkey_t based on keyname.
1248 if (tsigkey == NULL) {
1249 ret = ISC_R_NOTFOUND;
1251 ret = dns_tsigkey_find(&tsigkey, keyname,
1252 &tsig.algorithm, ring1);
1253 if (ret == ISC_R_NOTFOUND && ring2 != NULL)
1254 ret = dns_tsigkey_find(&tsigkey, keyname,
1255 &tsig.algorithm, ring2);
1256 if (ret != ISC_R_SUCCESS) {
1257 msg->tsigstatus = dns_tsigerror_badkey;
1258 ret = dns_tsigkey_create(keyname, &tsig.algorithm,
1259 NULL, 0, ISC_FALSE, NULL,
1261 mctx, NULL, &msg->tsigkey);
1262 if (ret != ISC_R_SUCCESS)
1264 tsig_log(msg->tsigkey, 2, "unknown key");
1265 return (DNS_R_TSIGVERIFYFAILURE);
1267 msg->tsigkey = tsigkey;
1275 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
1276 msg->tsigstatus = dns_tsigerror_badtime;
1277 tsig_log(msg->tsigkey, 2, "signature has expired");
1278 return (DNS_R_CLOCKSKEW);
1279 } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
1280 msg->tsigstatus = dns_tsigerror_badtime;
1281 tsig_log(msg->tsigkey, 2, "signature is in the future");
1282 return (DNS_R_CLOCKSKEW);
1286 * Check digest length.
1288 alg = dst_key_alg(key);
1289 ret = dst_key_sigsize(key, &siglen);
1290 if (ret != ISC_R_SUCCESS)
1292 if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 ||
1293 alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
1294 alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) {
1295 isc_uint16_t digestbits = dst_key_getbits(key);
1296 if (tsig.siglen > siglen) {
1297 tsig_log(msg->tsigkey, 2, "signature length to big");
1298 return (DNS_R_FORMERR);
1300 if (tsig.siglen > 0 &&
1301 (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) {
1302 tsig_log(msg->tsigkey, 2,
1303 "signature length below minimum");
1304 return (DNS_R_FORMERR);
1306 if (tsig.siglen > 0 && digestbits != 0 &&
1307 tsig.siglen < ((digestbits + 1) / 8)) {
1308 msg->tsigstatus = dns_tsigerror_badtrunc;
1309 tsig_log(msg->tsigkey, 2,
1310 "truncated signature length too small");
1311 return (DNS_R_TSIGVERIFYFAILURE);
1313 if (tsig.siglen > 0 && digestbits == 0 &&
1314 tsig.siglen < siglen) {
1315 msg->tsigstatus = dns_tsigerror_badtrunc;
1316 tsig_log(msg->tsigkey, 2, "signature length too small");
1317 return (DNS_R_TSIGVERIFYFAILURE);
1321 if (tsig.siglen > 0) {
1322 sig_r.base = tsig.signature;
1323 sig_r.length = tsig.siglen;
1325 ret = dst_context_create(key, mctx, &ctx);
1326 if (ret != ISC_R_SUCCESS)
1329 if (is_response(msg)) {
1330 isc_buffer_init(&databuf, data, sizeof(data));
1331 isc_buffer_putuint16(&databuf, querytsig.siglen);
1332 isc_buffer_usedregion(&databuf, &r);
1333 ret = dst_context_adddata(ctx, &r);
1334 if (ret != ISC_R_SUCCESS)
1335 goto cleanup_context;
1336 if (querytsig.siglen > 0) {
1337 r.length = querytsig.siglen;
1338 r.base = querytsig.signature;
1339 ret = dst_context_adddata(ctx, &r);
1340 if (ret != ISC_R_SUCCESS)
1341 goto cleanup_context;
1346 * Extract the header.
1348 isc_buffer_usedregion(source, &r);
1349 memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
1350 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1353 * Decrement the additional field counter.
1355 memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
1356 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
1357 memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
1360 * Put in the original id.
1362 id = htons(tsig.originalid);
1363 memcpy(&header[0], &id, 2);
1366 * Digest the modified header.
1368 header_r.base = (unsigned char *) header;
1369 header_r.length = DNS_MESSAGE_HEADERLEN;
1370 ret = dst_context_adddata(ctx, &header_r);
1371 if (ret != ISC_R_SUCCESS)
1372 goto cleanup_context;
1375 * Digest all non-TSIG records.
1377 isc_buffer_usedregion(source, &source_r);
1378 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
1379 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
1380 ret = dst_context_adddata(ctx, &r);
1381 if (ret != ISC_R_SUCCESS)
1382 goto cleanup_context;
1385 * Digest the key name.
1387 dns_name_toregion(&tsigkey->name, &r);
1388 ret = dst_context_adddata(ctx, &r);
1389 if (ret != ISC_R_SUCCESS)
1390 goto cleanup_context;
1392 isc_buffer_init(&databuf, data, sizeof(data));
1393 isc_buffer_putuint16(&databuf, tsig.common.rdclass);
1394 isc_buffer_putuint32(&databuf, msg->tsig->ttl);
1395 isc_buffer_usedregion(&databuf, &r);
1396 ret = dst_context_adddata(ctx, &r);
1397 if (ret != ISC_R_SUCCESS)
1398 goto cleanup_context;
1401 * Digest the key algorithm.
1403 dns_name_toregion(tsigkey->algorithm, &r);
1404 ret = dst_context_adddata(ctx, &r);
1405 if (ret != ISC_R_SUCCESS)
1406 goto cleanup_context;
1408 isc_buffer_clear(&databuf);
1409 isc_buffer_putuint48(&databuf, tsig.timesigned);
1410 isc_buffer_putuint16(&databuf, tsig.fudge);
1411 isc_buffer_putuint16(&databuf, tsig.error);
1412 isc_buffer_putuint16(&databuf, tsig.otherlen);
1413 isc_buffer_usedregion(&databuf, &r);
1414 ret = dst_context_adddata(ctx, &r);
1415 if (ret != ISC_R_SUCCESS)
1416 goto cleanup_context;
1418 if (tsig.otherlen > 0) {
1419 r.base = tsig.other;
1420 r.length = tsig.otherlen;
1421 ret = dst_context_adddata(ctx, &r);
1422 if (ret != ISC_R_SUCCESS)
1423 goto cleanup_context;
1426 ret = dst_context_verify(ctx, &sig_r);
1427 if (ret == DST_R_VERIFYFAILURE) {
1428 msg->tsigstatus = dns_tsigerror_badsig;
1429 ret = DNS_R_TSIGVERIFYFAILURE;
1430 tsig_log(msg->tsigkey, 2,
1431 "signature failed to verify(1)");
1432 goto cleanup_context;
1433 } else if (ret != ISC_R_SUCCESS)
1434 goto cleanup_context;
1436 dst_context_destroy(&ctx);
1437 } else if (tsig.error != dns_tsigerror_badsig &&
1438 tsig.error != dns_tsigerror_badkey) {
1439 msg->tsigstatus = dns_tsigerror_badsig;
1440 tsig_log(msg->tsigkey, 2, "signature was empty");
1441 return (DNS_R_TSIGVERIFYFAILURE);
1444 msg->tsigstatus = dns_rcode_noerror;
1446 if (tsig.error != dns_rcode_noerror) {
1447 if (tsig.error == dns_tsigerror_badtime)
1448 return (DNS_R_CLOCKSKEW);
1450 return (DNS_R_TSIGERRORSET);
1453 msg->verified_sig = 1;
1455 return (ISC_R_SUCCESS);
1459 dst_context_destroy(&ctx);
1465 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
1466 dns_rdata_any_tsig_t tsig, querytsig;
1467 isc_region_t r, source_r, header_r, sig_r;
1468 isc_buffer_t databuf;
1469 unsigned char data[32];
1470 dns_name_t *keyname;
1471 dns_rdata_t rdata = DNS_RDATA_INIT;
1474 dns_tsigkey_t *tsigkey;
1475 dst_key_t *key = NULL;
1476 unsigned char header[DNS_MESSAGE_HEADERLEN];
1477 isc_uint16_t addcount, id;
1478 isc_boolean_t has_tsig = ISC_FALSE;
1481 REQUIRE(source != NULL);
1482 REQUIRE(msg != NULL);
1483 REQUIRE(dns_message_gettsigkey(msg) != NULL);
1484 REQUIRE(msg->tcp_continuation == 1);
1485 REQUIRE(msg->querytsig != NULL);
1487 if (!is_response(msg))
1488 return (DNS_R_EXPECTEDRESPONSE);
1492 tsigkey = dns_message_gettsigkey(msg);
1495 * Extract and parse the previous TSIG
1497 ret = dns_rdataset_first(msg->querytsig);
1498 if (ret != ISC_R_SUCCESS)
1500 dns_rdataset_current(msg->querytsig, &rdata);
1501 ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
1502 if (ret != ISC_R_SUCCESS)
1504 dns_rdata_reset(&rdata);
1507 * If there is a TSIG in this message, do some checks.
1509 if (msg->tsig != NULL) {
1510 has_tsig = ISC_TRUE;
1512 keyname = msg->tsigname;
1513 ret = dns_rdataset_first(msg->tsig);
1514 if (ret != ISC_R_SUCCESS)
1515 goto cleanup_querystruct;
1516 dns_rdataset_current(msg->tsig, &rdata);
1517 ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
1518 if (ret != ISC_R_SUCCESS)
1519 goto cleanup_querystruct;
1522 * Do the key name and algorithm match that of the query?
1524 if (!dns_name_equal(keyname, &tsigkey->name) ||
1525 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) {
1526 msg->tsigstatus = dns_tsigerror_badkey;
1527 ret = DNS_R_TSIGVERIFYFAILURE;
1528 tsig_log(msg->tsigkey, 2,
1529 "key name and algorithm do not match");
1530 goto cleanup_querystruct;
1536 isc_stdtime_get(&now);
1538 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
1539 msg->tsigstatus = dns_tsigerror_badtime;
1540 tsig_log(msg->tsigkey, 2, "signature has expired");
1541 ret = DNS_R_CLOCKSKEW;
1542 goto cleanup_querystruct;
1543 } else if (now + msg->timeadjust <
1544 tsig.timesigned - tsig.fudge) {
1545 msg->tsigstatus = dns_tsigerror_badtime;
1546 tsig_log(msg->tsigkey, 2,
1547 "signature is in the future");
1548 ret = DNS_R_CLOCKSKEW;
1549 goto cleanup_querystruct;
1555 if (msg->tsigctx == NULL) {
1556 ret = dst_context_create(key, mctx, &msg->tsigctx);
1557 if (ret != ISC_R_SUCCESS)
1558 goto cleanup_querystruct;
1561 * Digest the length of the query signature
1563 isc_buffer_init(&databuf, data, sizeof(data));
1564 isc_buffer_putuint16(&databuf, querytsig.siglen);
1565 isc_buffer_usedregion(&databuf, &r);
1566 ret = dst_context_adddata(msg->tsigctx, &r);
1567 if (ret != ISC_R_SUCCESS)
1568 goto cleanup_context;
1571 * Digest the data of the query signature
1573 if (querytsig.siglen > 0) {
1574 r.length = querytsig.siglen;
1575 r.base = querytsig.signature;
1576 ret = dst_context_adddata(msg->tsigctx, &r);
1577 if (ret != ISC_R_SUCCESS)
1578 goto cleanup_context;
1583 * Extract the header.
1585 isc_buffer_usedregion(source, &r);
1586 memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
1587 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1590 * Decrement the additional field counter if necessary.
1593 memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
1594 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
1595 memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
1599 * Put in the original id.
1601 /* XXX Can TCP transfers be forwarded? How would that work? */
1603 id = htons(tsig.originalid);
1604 memcpy(&header[0], &id, 2);
1608 * Digest the modified header.
1610 header_r.base = (unsigned char *) header;
1611 header_r.length = DNS_MESSAGE_HEADERLEN;
1612 ret = dst_context_adddata(msg->tsigctx, &header_r);
1613 if (ret != ISC_R_SUCCESS)
1614 goto cleanup_context;
1617 * Digest all non-TSIG records.
1619 isc_buffer_usedregion(source, &source_r);
1620 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
1622 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
1624 r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
1625 ret = dst_context_adddata(msg->tsigctx, &r);
1626 if (ret != ISC_R_SUCCESS)
1627 goto cleanup_context;
1630 * Digest the time signed and fudge.
1633 isc_buffer_init(&databuf, data, sizeof(data));
1634 isc_buffer_putuint48(&databuf, tsig.timesigned);
1635 isc_buffer_putuint16(&databuf, tsig.fudge);
1636 isc_buffer_usedregion(&databuf, &r);
1637 ret = dst_context_adddata(msg->tsigctx, &r);
1638 if (ret != ISC_R_SUCCESS)
1639 goto cleanup_context;
1641 sig_r.base = tsig.signature;
1642 sig_r.length = tsig.siglen;
1643 if (tsig.siglen == 0) {
1644 if (tsig.error != dns_rcode_noerror) {
1645 if (tsig.error == dns_tsigerror_badtime)
1646 ret = DNS_R_CLOCKSKEW;
1648 ret = DNS_R_TSIGERRORSET;
1650 tsig_log(msg->tsigkey, 2,
1651 "signature is empty");
1652 ret = DNS_R_TSIGVERIFYFAILURE;
1654 goto cleanup_context;
1657 ret = dst_context_verify(msg->tsigctx, &sig_r);
1658 if (ret == DST_R_VERIFYFAILURE) {
1659 msg->tsigstatus = dns_tsigerror_badsig;
1660 tsig_log(msg->tsigkey, 2,
1661 "signature failed to verify(2)");
1662 ret = DNS_R_TSIGVERIFYFAILURE;
1663 goto cleanup_context;
1665 else if (ret != ISC_R_SUCCESS)
1666 goto cleanup_context;
1668 dst_context_destroy(&msg->tsigctx);
1671 msg->tsigstatus = dns_rcode_noerror;
1672 return (ISC_R_SUCCESS);
1675 dst_context_destroy(&msg->tsigctx);
1677 cleanup_querystruct:
1678 dns_rdata_freestruct(&querytsig);
1685 dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
1686 dns_name_t *algorithm, dns_tsig_keyring_t *ring)
1690 isc_result_t result;
1692 REQUIRE(tsigkey != NULL);
1693 REQUIRE(*tsigkey == NULL);
1694 REQUIRE(name != NULL);
1695 REQUIRE(ring != NULL);
1697 RWLOCK(&ring->lock, isc_rwlocktype_write);
1699 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
1701 isc_stdtime_get(&now);
1702 RWLOCK(&ring->lock, isc_rwlocktype_read);
1704 result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
1705 if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
1706 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1707 return (ISC_R_NOTFOUND);
1709 if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
1710 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1711 return (ISC_R_NOTFOUND);
1713 if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
1715 * The key has expired.
1717 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1718 RWLOCK(&ring->lock, isc_rwlocktype_write);
1719 remove_fromring(key);
1720 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
1721 return (ISC_R_NOTFOUND);
1725 * MPAXXX We really should look at the inception time.
1727 if (key->inception != key->expire &&
1728 isc_serial_lt(key->inception, now)) {
1729 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1731 return (ISC_R_NOTFOUND);
1734 isc_refcount_increment(&key->refs, NULL);
1735 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1738 return (ISC_R_SUCCESS);
1742 free_tsignode(void *node, void *_unused) {
1747 REQUIRE(node != NULL);
1750 dns_tsigkey_detach(&key);
1754 dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
1755 isc_result_t result;
1756 dns_tsig_keyring_t *ring;
1758 REQUIRE(mctx != NULL);
1759 REQUIRE(ringp != NULL);
1760 REQUIRE(*ringp == NULL);
1762 ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
1764 return (ISC_R_NOMEMORY);
1766 result = isc_rwlock_init(&ring->lock, 0, 0);
1767 if (result != ISC_R_SUCCESS) {
1768 isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
1773 result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
1774 if (result != ISC_R_SUCCESS) {
1775 isc_rwlock_destroy(&ring->lock);
1776 isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
1780 ring->writecount = 0;
1782 ring->generated = 0;
1783 ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
1784 ISC_LIST_INIT(ring->lru);
1785 isc_mem_attach(mctx, &ring->mctx);
1786 ring->references = 1;
1789 return (ISC_R_SUCCESS);
1793 dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
1794 dns_tsigkey_t *tkey)
1796 isc_result_t result;
1798 result = keyring_add(ring, name, tkey);
1799 if (result == ISC_R_SUCCESS)
1800 isc_refcount_increment(&tkey->refs, NULL);
1806 dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
1808 REQUIRE(source != NULL);
1809 REQUIRE(target != NULL && *target == NULL);
1811 RWLOCK(&source->lock, isc_rwlocktype_write);
1812 INSIST(source->references > 0);
1813 source->references++;
1814 INSIST(source->references > 0);
1816 RWUNLOCK(&source->lock, isc_rwlocktype_write);
1820 dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
1821 dns_tsig_keyring_t *ring;
1822 unsigned int references;
1824 REQUIRE(ringp != NULL);
1825 REQUIRE(*ringp != NULL);
1830 RWLOCK(&ring->lock, isc_rwlocktype_write);
1831 INSIST(ring->references > 0);
1833 references = ring->references;
1834 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
1836 if (references == 0)
1841 dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) {
1843 isc_result_t result;
1845 isc_stdtime_get(&now);
1847 result = restore_key(ring, now, fp);
1848 if (result == ISC_R_NOMORE)
1850 if (result == DNS_R_BADALG || result == DNS_R_EXPIRED)
1851 result = ISC_R_SUCCESS;
1852 } while (result == ISC_R_SUCCESS);