2 * Copyright (C) 2004-2012 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.
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;
892 isc_boolean_t response = is_response(msg);
894 REQUIRE(msg != NULL);
895 REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg)));
898 * If this is a response, there should be a query tsig.
900 if (response && msg->querytsig == NULL)
901 return (DNS_R_EXPECTEDTSIG);
906 key = dns_message_gettsigkey(msg);
909 tsig.common.rdclass = dns_rdataclass_any;
910 tsig.common.rdtype = dns_rdatatype_tsig;
911 ISC_LINK_INIT(&tsig.common, link);
912 dns_name_init(&tsig.algorithm, NULL);
913 dns_name_clone(key->algorithm, &tsig.algorithm);
915 isc_stdtime_get(&now);
916 tsig.timesigned = now + msg->timeadjust;
917 tsig.fudge = DNS_TSIG_FUDGE;
919 tsig.originalid = msg->id;
921 isc_buffer_init(&databuf, data, sizeof(data));
924 tsig.error = msg->querytsigstatus;
926 tsig.error = dns_rcode_noerror;
928 if (tsig.error != dns_tsigerror_badtime) {
932 isc_buffer_t otherbuf;
934 tsig.otherlen = BADTIMELEN;
935 tsig.other = badtimedata;
936 isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
937 isc_buffer_putuint48(&otherbuf, tsig.timesigned);
940 if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
941 unsigned char header[DNS_MESSAGE_HEADERLEN];
942 isc_buffer_t headerbuf;
943 isc_uint16_t digestbits;
945 ret = dst_context_create(key->key, mctx, &ctx);
946 if (ret != ISC_R_SUCCESS)
950 * If this is a response, digest the query signature.
953 dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
955 ret = dns_rdataset_first(msg->querytsig);
956 if (ret != ISC_R_SUCCESS)
957 goto cleanup_context;
958 dns_rdataset_current(msg->querytsig, &querytsigrdata);
959 ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
961 if (ret != ISC_R_SUCCESS)
962 goto cleanup_context;
963 isc_buffer_putuint16(&databuf, querytsig.siglen);
964 if (isc_buffer_availablelength(&databuf) <
967 goto cleanup_context;
969 isc_buffer_putmem(&databuf, querytsig.signature,
971 isc_buffer_usedregion(&databuf, &r);
972 ret = dst_context_adddata(ctx, &r);
973 if (ret != ISC_R_SUCCESS)
974 goto cleanup_context;
980 isc_buffer_init(&headerbuf, header, sizeof(header));
981 dns_message_renderheader(msg, &headerbuf);
982 isc_buffer_usedregion(&headerbuf, &r);
983 ret = dst_context_adddata(ctx, &r);
984 if (ret != ISC_R_SUCCESS)
985 goto cleanup_context;
988 * Digest the remainder of the message.
990 isc_buffer_usedregion(msg->buffer, &r);
991 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
992 ret = dst_context_adddata(ctx, &r);
993 if (ret != ISC_R_SUCCESS)
994 goto cleanup_context;
996 if (msg->tcp_continuation == 0) {
998 * Digest the name, class, ttl, alg.
1000 dns_name_toregion(&key->name, &r);
1001 ret = dst_context_adddata(ctx, &r);
1002 if (ret != ISC_R_SUCCESS)
1003 goto cleanup_context;
1005 isc_buffer_clear(&databuf);
1006 isc_buffer_putuint16(&databuf, dns_rdataclass_any);
1007 isc_buffer_putuint32(&databuf, 0); /* ttl */
1008 isc_buffer_usedregion(&databuf, &r);
1009 ret = dst_context_adddata(ctx, &r);
1010 if (ret != ISC_R_SUCCESS)
1011 goto cleanup_context;
1013 dns_name_toregion(&tsig.algorithm, &r);
1014 ret = dst_context_adddata(ctx, &r);
1015 if (ret != ISC_R_SUCCESS)
1016 goto cleanup_context;
1019 /* Digest the timesigned and fudge */
1020 isc_buffer_clear(&databuf);
1021 if (tsig.error == dns_tsigerror_badtime) {
1023 tsig.timesigned = querytsig.timesigned;
1025 isc_buffer_putuint48(&databuf, tsig.timesigned);
1026 isc_buffer_putuint16(&databuf, tsig.fudge);
1027 isc_buffer_usedregion(&databuf, &r);
1028 ret = dst_context_adddata(ctx, &r);
1029 if (ret != ISC_R_SUCCESS)
1030 goto cleanup_context;
1032 if (msg->tcp_continuation == 0) {
1034 * Digest the error and other data length.
1036 isc_buffer_clear(&databuf);
1037 isc_buffer_putuint16(&databuf, tsig.error);
1038 isc_buffer_putuint16(&databuf, tsig.otherlen);
1040 isc_buffer_usedregion(&databuf, &r);
1041 ret = dst_context_adddata(ctx, &r);
1042 if (ret != ISC_R_SUCCESS)
1043 goto cleanup_context;
1046 * Digest other data.
1048 if (tsig.otherlen > 0) {
1049 r.length = tsig.otherlen;
1050 r.base = tsig.other;
1051 ret = dst_context_adddata(ctx, &r);
1052 if (ret != ISC_R_SUCCESS)
1053 goto cleanup_context;
1057 ret = dst_key_sigsize(key->key, &sigsize);
1058 if (ret != ISC_R_SUCCESS)
1059 goto cleanup_context;
1060 tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
1061 if (tsig.signature == NULL) {
1062 ret = ISC_R_NOMEMORY;
1063 goto cleanup_context;
1066 isc_buffer_init(&sigbuf, tsig.signature, sigsize);
1067 ret = dst_context_sign(ctx, &sigbuf);
1068 if (ret != ISC_R_SUCCESS)
1069 goto cleanup_signature;
1070 dst_context_destroy(&ctx);
1071 digestbits = dst_key_getbits(key->key);
1072 if (digestbits != 0) {
1073 unsigned int bytes = (digestbits + 1) / 8;
1074 if (response && bytes < querytsig.siglen)
1075 bytes = querytsig.siglen;
1076 if (bytes > isc_buffer_usedlength(&sigbuf))
1077 bytes = isc_buffer_usedlength(&sigbuf);
1078 tsig.siglen = bytes;
1080 tsig.siglen = isc_buffer_usedlength(&sigbuf);
1083 tsig.signature = NULL;
1086 ret = dns_message_gettemprdata(msg, &rdata);
1087 if (ret != ISC_R_SUCCESS)
1088 goto cleanup_signature;
1089 ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
1090 if (ret != ISC_R_SUCCESS)
1092 ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
1093 dns_rdatatype_tsig, &tsig, dynbuf);
1094 if (ret != ISC_R_SUCCESS)
1095 goto cleanup_dynbuf;
1097 dns_message_takebuffer(msg, &dynbuf);
1099 if (tsig.signature != NULL) {
1100 isc_mem_put(mctx, tsig.signature, sigsize);
1101 tsig.signature = NULL;
1105 ret = dns_message_gettempname(msg, &owner);
1106 if (ret != ISC_R_SUCCESS)
1108 dns_name_init(owner, NULL);
1109 ret = dns_name_dup(&key->name, msg->mctx, owner);
1110 if (ret != ISC_R_SUCCESS)
1114 ret = dns_message_gettemprdatalist(msg, &datalist);
1115 if (ret != ISC_R_SUCCESS)
1118 ret = dns_message_gettemprdataset(msg, &dataset);
1119 if (ret != ISC_R_SUCCESS)
1120 goto cleanup_rdatalist;
1121 datalist->rdclass = dns_rdataclass_any;
1122 datalist->type = dns_rdatatype_tsig;
1123 datalist->covers = 0;
1125 ISC_LIST_INIT(datalist->rdata);
1126 ISC_LIST_APPEND(datalist->rdata, rdata, link);
1127 dns_rdataset_init(dataset);
1128 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
1130 msg->tsig = dataset;
1131 msg->tsigname = owner;
1133 /* Windows does not like the tsig name being compressed. */
1134 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
1136 return (ISC_R_SUCCESS);
1139 dns_message_puttemprdatalist(msg, &datalist);
1141 dns_message_puttempname(msg, &owner);
1144 isc_buffer_free(&dynbuf);
1146 dns_message_puttemprdata(msg, &rdata);
1148 if (tsig.signature != NULL)
1149 isc_mem_put(mctx, tsig.signature, sigsize);
1152 dst_context_destroy(&ctx);
1157 dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
1158 dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2)
1160 dns_rdata_any_tsig_t tsig, querytsig;
1161 isc_region_t r, source_r, header_r, sig_r;
1162 isc_buffer_t databuf;
1163 unsigned char data[32];
1164 dns_name_t *keyname;
1165 dns_rdata_t rdata = DNS_RDATA_INIT;
1168 dns_tsigkey_t *tsigkey;
1169 dst_key_t *key = NULL;
1170 unsigned char header[DNS_MESSAGE_HEADERLEN];
1171 dst_context_t *ctx = NULL;
1173 isc_uint16_t addcount, id;
1174 unsigned int siglen;
1176 isc_boolean_t response;
1178 REQUIRE(source != NULL);
1179 REQUIRE(DNS_MESSAGE_VALID(msg));
1180 tsigkey = dns_message_gettsigkey(msg);
1181 response = is_response(msg);
1183 REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
1185 msg->verify_attempted = 1;
1187 if (msg->tcp_continuation) {
1188 if (tsigkey == NULL || msg->querytsig == NULL)
1189 return (DNS_R_UNEXPECTEDTSIG);
1190 return (tsig_verify_tcp(source, msg));
1194 * There should be a TSIG record...
1196 if (msg->tsig == NULL)
1197 return (DNS_R_EXPECTEDTSIG);
1200 * If this is a response and there's no key or query TSIG, there
1201 * shouldn't be one on the response.
1203 if (response && (tsigkey == NULL || msg->querytsig == NULL))
1204 return (DNS_R_UNEXPECTEDTSIG);
1209 * If we're here, we know the message is well formed and contains a
1213 keyname = msg->tsigname;
1214 ret = dns_rdataset_first(msg->tsig);
1215 if (ret != ISC_R_SUCCESS)
1217 dns_rdataset_current(msg->tsig, &rdata);
1218 ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
1219 if (ret != ISC_R_SUCCESS)
1221 dns_rdata_reset(&rdata);
1223 ret = dns_rdataset_first(msg->querytsig);
1224 if (ret != ISC_R_SUCCESS)
1226 dns_rdataset_current(msg->querytsig, &rdata);
1227 ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
1228 if (ret != ISC_R_SUCCESS)
1233 * Do the key name and algorithm match that of the query?
1236 (!dns_name_equal(keyname, &tsigkey->name) ||
1237 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
1238 msg->tsigstatus = dns_tsigerror_badkey;
1239 tsig_log(msg->tsigkey, 2,
1240 "key name and algorithm do not match");
1241 return (DNS_R_TSIGVERIFYFAILURE);
1245 * Get the current time.
1247 isc_stdtime_get(&now);
1250 * Find dns_tsigkey_t based on keyname.
1252 if (tsigkey == NULL) {
1253 ret = ISC_R_NOTFOUND;
1255 ret = dns_tsigkey_find(&tsigkey, keyname,
1256 &tsig.algorithm, ring1);
1257 if (ret == ISC_R_NOTFOUND && ring2 != NULL)
1258 ret = dns_tsigkey_find(&tsigkey, keyname,
1259 &tsig.algorithm, ring2);
1260 if (ret != ISC_R_SUCCESS) {
1261 msg->tsigstatus = dns_tsigerror_badkey;
1262 ret = dns_tsigkey_create(keyname, &tsig.algorithm,
1263 NULL, 0, ISC_FALSE, NULL,
1265 mctx, NULL, &msg->tsigkey);
1266 if (ret != ISC_R_SUCCESS)
1268 tsig_log(msg->tsigkey, 2, "unknown key");
1269 return (DNS_R_TSIGVERIFYFAILURE);
1271 msg->tsigkey = tsigkey;
1279 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
1280 msg->tsigstatus = dns_tsigerror_badtime;
1281 tsig_log(msg->tsigkey, 2, "signature has expired");
1282 return (DNS_R_CLOCKSKEW);
1283 } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
1284 msg->tsigstatus = dns_tsigerror_badtime;
1285 tsig_log(msg->tsigkey, 2, "signature is in the future");
1286 return (DNS_R_CLOCKSKEW);
1290 * Check digest length.
1292 alg = dst_key_alg(key);
1293 ret = dst_key_sigsize(key, &siglen);
1294 if (ret != ISC_R_SUCCESS)
1296 if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 ||
1297 alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
1298 alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) {
1299 isc_uint16_t digestbits = dst_key_getbits(key);
1300 if (tsig.siglen > siglen) {
1301 tsig_log(msg->tsigkey, 2, "signature length to big");
1302 return (DNS_R_FORMERR);
1304 if (tsig.siglen > 0 &&
1305 (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) {
1306 tsig_log(msg->tsigkey, 2,
1307 "signature length below minimum");
1308 return (DNS_R_FORMERR);
1310 if (tsig.siglen > 0 && digestbits != 0 &&
1311 tsig.siglen < ((digestbits + 1) / 8)) {
1312 msg->tsigstatus = dns_tsigerror_badtrunc;
1313 tsig_log(msg->tsigkey, 2,
1314 "truncated signature length too small");
1315 return (DNS_R_TSIGVERIFYFAILURE);
1317 if (tsig.siglen > 0 && digestbits == 0 &&
1318 tsig.siglen < siglen) {
1319 msg->tsigstatus = dns_tsigerror_badtrunc;
1320 tsig_log(msg->tsigkey, 2, "signature length too small");
1321 return (DNS_R_TSIGVERIFYFAILURE);
1325 if (tsig.siglen > 0) {
1326 sig_r.base = tsig.signature;
1327 sig_r.length = tsig.siglen;
1329 ret = dst_context_create(key, mctx, &ctx);
1330 if (ret != ISC_R_SUCCESS)
1334 isc_buffer_init(&databuf, data, sizeof(data));
1335 isc_buffer_putuint16(&databuf, querytsig.siglen);
1336 isc_buffer_usedregion(&databuf, &r);
1337 ret = dst_context_adddata(ctx, &r);
1338 if (ret != ISC_R_SUCCESS)
1339 goto cleanup_context;
1340 if (querytsig.siglen > 0) {
1341 r.length = querytsig.siglen;
1342 r.base = querytsig.signature;
1343 ret = dst_context_adddata(ctx, &r);
1344 if (ret != ISC_R_SUCCESS)
1345 goto cleanup_context;
1350 * Extract the header.
1352 isc_buffer_usedregion(source, &r);
1353 memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
1354 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1357 * Decrement the additional field counter.
1359 memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
1360 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
1361 memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
1364 * Put in the original id.
1366 id = htons(tsig.originalid);
1367 memcpy(&header[0], &id, 2);
1370 * Digest the modified header.
1372 header_r.base = (unsigned char *) header;
1373 header_r.length = DNS_MESSAGE_HEADERLEN;
1374 ret = dst_context_adddata(ctx, &header_r);
1375 if (ret != ISC_R_SUCCESS)
1376 goto cleanup_context;
1379 * Digest all non-TSIG records.
1381 isc_buffer_usedregion(source, &source_r);
1382 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
1383 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
1384 ret = dst_context_adddata(ctx, &r);
1385 if (ret != ISC_R_SUCCESS)
1386 goto cleanup_context;
1389 * Digest the key name.
1391 dns_name_toregion(&tsigkey->name, &r);
1392 ret = dst_context_adddata(ctx, &r);
1393 if (ret != ISC_R_SUCCESS)
1394 goto cleanup_context;
1396 isc_buffer_init(&databuf, data, sizeof(data));
1397 isc_buffer_putuint16(&databuf, tsig.common.rdclass);
1398 isc_buffer_putuint32(&databuf, msg->tsig->ttl);
1399 isc_buffer_usedregion(&databuf, &r);
1400 ret = dst_context_adddata(ctx, &r);
1401 if (ret != ISC_R_SUCCESS)
1402 goto cleanup_context;
1405 * Digest the key algorithm.
1407 dns_name_toregion(tsigkey->algorithm, &r);
1408 ret = dst_context_adddata(ctx, &r);
1409 if (ret != ISC_R_SUCCESS)
1410 goto cleanup_context;
1412 isc_buffer_clear(&databuf);
1413 isc_buffer_putuint48(&databuf, tsig.timesigned);
1414 isc_buffer_putuint16(&databuf, tsig.fudge);
1415 isc_buffer_putuint16(&databuf, tsig.error);
1416 isc_buffer_putuint16(&databuf, tsig.otherlen);
1417 isc_buffer_usedregion(&databuf, &r);
1418 ret = dst_context_adddata(ctx, &r);
1419 if (ret != ISC_R_SUCCESS)
1420 goto cleanup_context;
1422 if (tsig.otherlen > 0) {
1423 r.base = tsig.other;
1424 r.length = tsig.otherlen;
1425 ret = dst_context_adddata(ctx, &r);
1426 if (ret != ISC_R_SUCCESS)
1427 goto cleanup_context;
1430 ret = dst_context_verify(ctx, &sig_r);
1431 if (ret == DST_R_VERIFYFAILURE) {
1432 msg->tsigstatus = dns_tsigerror_badsig;
1433 ret = DNS_R_TSIGVERIFYFAILURE;
1434 tsig_log(msg->tsigkey, 2,
1435 "signature failed to verify(1)");
1436 goto cleanup_context;
1437 } else if (ret != ISC_R_SUCCESS)
1438 goto cleanup_context;
1440 dst_context_destroy(&ctx);
1441 } else if (tsig.error != dns_tsigerror_badsig &&
1442 tsig.error != dns_tsigerror_badkey) {
1443 msg->tsigstatus = dns_tsigerror_badsig;
1444 tsig_log(msg->tsigkey, 2, "signature was empty");
1445 return (DNS_R_TSIGVERIFYFAILURE);
1448 msg->tsigstatus = dns_rcode_noerror;
1450 if (tsig.error != dns_rcode_noerror) {
1451 if (tsig.error == dns_tsigerror_badtime)
1452 return (DNS_R_CLOCKSKEW);
1454 return (DNS_R_TSIGERRORSET);
1457 msg->verified_sig = 1;
1459 return (ISC_R_SUCCESS);
1463 dst_context_destroy(&ctx);
1469 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
1470 dns_rdata_any_tsig_t tsig, querytsig;
1471 isc_region_t r, source_r, header_r, sig_r;
1472 isc_buffer_t databuf;
1473 unsigned char data[32];
1474 dns_name_t *keyname;
1475 dns_rdata_t rdata = DNS_RDATA_INIT;
1478 dns_tsigkey_t *tsigkey;
1479 dst_key_t *key = NULL;
1480 unsigned char header[DNS_MESSAGE_HEADERLEN];
1481 isc_uint16_t addcount, id;
1482 isc_boolean_t has_tsig = ISC_FALSE;
1485 REQUIRE(source != NULL);
1486 REQUIRE(msg != NULL);
1487 REQUIRE(dns_message_gettsigkey(msg) != NULL);
1488 REQUIRE(msg->tcp_continuation == 1);
1489 REQUIRE(msg->querytsig != NULL);
1491 if (!is_response(msg))
1492 return (DNS_R_EXPECTEDRESPONSE);
1496 tsigkey = dns_message_gettsigkey(msg);
1499 * Extract and parse the previous TSIG
1501 ret = dns_rdataset_first(msg->querytsig);
1502 if (ret != ISC_R_SUCCESS)
1504 dns_rdataset_current(msg->querytsig, &rdata);
1505 ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
1506 if (ret != ISC_R_SUCCESS)
1508 dns_rdata_reset(&rdata);
1511 * If there is a TSIG in this message, do some checks.
1513 if (msg->tsig != NULL) {
1514 has_tsig = ISC_TRUE;
1516 keyname = msg->tsigname;
1517 ret = dns_rdataset_first(msg->tsig);
1518 if (ret != ISC_R_SUCCESS)
1519 goto cleanup_querystruct;
1520 dns_rdataset_current(msg->tsig, &rdata);
1521 ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
1522 if (ret != ISC_R_SUCCESS)
1523 goto cleanup_querystruct;
1526 * Do the key name and algorithm match that of the query?
1528 if (!dns_name_equal(keyname, &tsigkey->name) ||
1529 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) {
1530 msg->tsigstatus = dns_tsigerror_badkey;
1531 ret = DNS_R_TSIGVERIFYFAILURE;
1532 tsig_log(msg->tsigkey, 2,
1533 "key name and algorithm do not match");
1534 goto cleanup_querystruct;
1540 isc_stdtime_get(&now);
1542 if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
1543 msg->tsigstatus = dns_tsigerror_badtime;
1544 tsig_log(msg->tsigkey, 2, "signature has expired");
1545 ret = DNS_R_CLOCKSKEW;
1546 goto cleanup_querystruct;
1547 } else if (now + msg->timeadjust <
1548 tsig.timesigned - tsig.fudge) {
1549 msg->tsigstatus = dns_tsigerror_badtime;
1550 tsig_log(msg->tsigkey, 2,
1551 "signature is in the future");
1552 ret = DNS_R_CLOCKSKEW;
1553 goto cleanup_querystruct;
1559 if (msg->tsigctx == NULL) {
1560 ret = dst_context_create(key, mctx, &msg->tsigctx);
1561 if (ret != ISC_R_SUCCESS)
1562 goto cleanup_querystruct;
1565 * Digest the length of the query signature
1567 isc_buffer_init(&databuf, data, sizeof(data));
1568 isc_buffer_putuint16(&databuf, querytsig.siglen);
1569 isc_buffer_usedregion(&databuf, &r);
1570 ret = dst_context_adddata(msg->tsigctx, &r);
1571 if (ret != ISC_R_SUCCESS)
1572 goto cleanup_context;
1575 * Digest the data of the query signature
1577 if (querytsig.siglen > 0) {
1578 r.length = querytsig.siglen;
1579 r.base = querytsig.signature;
1580 ret = dst_context_adddata(msg->tsigctx, &r);
1581 if (ret != ISC_R_SUCCESS)
1582 goto cleanup_context;
1587 * Extract the header.
1589 isc_buffer_usedregion(source, &r);
1590 memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
1591 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1594 * Decrement the additional field counter if necessary.
1597 memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
1598 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
1599 memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
1603 * Put in the original id.
1605 /* XXX Can TCP transfers be forwarded? How would that work? */
1607 id = htons(tsig.originalid);
1608 memcpy(&header[0], &id, 2);
1612 * Digest the modified header.
1614 header_r.base = (unsigned char *) header;
1615 header_r.length = DNS_MESSAGE_HEADERLEN;
1616 ret = dst_context_adddata(msg->tsigctx, &header_r);
1617 if (ret != ISC_R_SUCCESS)
1618 goto cleanup_context;
1621 * Digest all non-TSIG records.
1623 isc_buffer_usedregion(source, &source_r);
1624 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
1626 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
1628 r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
1629 ret = dst_context_adddata(msg->tsigctx, &r);
1630 if (ret != ISC_R_SUCCESS)
1631 goto cleanup_context;
1634 * Digest the time signed and fudge.
1637 isc_buffer_init(&databuf, data, sizeof(data));
1638 isc_buffer_putuint48(&databuf, tsig.timesigned);
1639 isc_buffer_putuint16(&databuf, tsig.fudge);
1640 isc_buffer_usedregion(&databuf, &r);
1641 ret = dst_context_adddata(msg->tsigctx, &r);
1642 if (ret != ISC_R_SUCCESS)
1643 goto cleanup_context;
1645 sig_r.base = tsig.signature;
1646 sig_r.length = tsig.siglen;
1647 if (tsig.siglen == 0) {
1648 if (tsig.error != dns_rcode_noerror) {
1649 if (tsig.error == dns_tsigerror_badtime)
1650 ret = DNS_R_CLOCKSKEW;
1652 ret = DNS_R_TSIGERRORSET;
1654 tsig_log(msg->tsigkey, 2,
1655 "signature is empty");
1656 ret = DNS_R_TSIGVERIFYFAILURE;
1658 goto cleanup_context;
1661 ret = dst_context_verify(msg->tsigctx, &sig_r);
1662 if (ret == DST_R_VERIFYFAILURE) {
1663 msg->tsigstatus = dns_tsigerror_badsig;
1664 tsig_log(msg->tsigkey, 2,
1665 "signature failed to verify(2)");
1666 ret = DNS_R_TSIGVERIFYFAILURE;
1667 goto cleanup_context;
1669 else if (ret != ISC_R_SUCCESS)
1670 goto cleanup_context;
1672 dst_context_destroy(&msg->tsigctx);
1675 msg->tsigstatus = dns_rcode_noerror;
1676 return (ISC_R_SUCCESS);
1679 dst_context_destroy(&msg->tsigctx);
1681 cleanup_querystruct:
1682 dns_rdata_freestruct(&querytsig);
1689 dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
1690 dns_name_t *algorithm, dns_tsig_keyring_t *ring)
1694 isc_result_t result;
1696 REQUIRE(tsigkey != NULL);
1697 REQUIRE(*tsigkey == NULL);
1698 REQUIRE(name != NULL);
1699 REQUIRE(ring != NULL);
1701 RWLOCK(&ring->lock, isc_rwlocktype_write);
1703 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
1705 isc_stdtime_get(&now);
1706 RWLOCK(&ring->lock, isc_rwlocktype_read);
1708 result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
1709 if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
1710 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1711 return (ISC_R_NOTFOUND);
1713 if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
1714 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1715 return (ISC_R_NOTFOUND);
1717 if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
1719 * The key has expired.
1721 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1722 RWLOCK(&ring->lock, isc_rwlocktype_write);
1723 remove_fromring(key);
1724 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
1725 return (ISC_R_NOTFOUND);
1729 * MPAXXX We really should look at the inception time.
1731 if (key->inception != key->expire &&
1732 isc_serial_lt(key->inception, now)) {
1733 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1735 return (ISC_R_NOTFOUND);
1738 isc_refcount_increment(&key->refs, NULL);
1739 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1742 return (ISC_R_SUCCESS);
1746 free_tsignode(void *node, void *_unused) {
1751 REQUIRE(node != NULL);
1754 dns_tsigkey_detach(&key);
1758 dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
1759 isc_result_t result;
1760 dns_tsig_keyring_t *ring;
1762 REQUIRE(mctx != NULL);
1763 REQUIRE(ringp != NULL);
1764 REQUIRE(*ringp == NULL);
1766 ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
1768 return (ISC_R_NOMEMORY);
1770 result = isc_rwlock_init(&ring->lock, 0, 0);
1771 if (result != ISC_R_SUCCESS) {
1772 isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
1777 result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
1778 if (result != ISC_R_SUCCESS) {
1779 isc_rwlock_destroy(&ring->lock);
1780 isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
1784 ring->writecount = 0;
1786 ring->generated = 0;
1787 ring->maxgenerated = DNS_TSIG_MAXGENERATEDKEYS;
1788 ISC_LIST_INIT(ring->lru);
1789 isc_mem_attach(mctx, &ring->mctx);
1790 ring->references = 1;
1793 return (ISC_R_SUCCESS);
1797 dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
1798 dns_tsigkey_t *tkey)
1800 isc_result_t result;
1802 result = keyring_add(ring, name, tkey);
1803 if (result == ISC_R_SUCCESS)
1804 isc_refcount_increment(&tkey->refs, NULL);
1810 dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
1812 REQUIRE(source != NULL);
1813 REQUIRE(target != NULL && *target == NULL);
1815 RWLOCK(&source->lock, isc_rwlocktype_write);
1816 INSIST(source->references > 0);
1817 source->references++;
1818 INSIST(source->references > 0);
1820 RWUNLOCK(&source->lock, isc_rwlocktype_write);
1824 dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
1825 dns_tsig_keyring_t *ring;
1826 unsigned int references;
1828 REQUIRE(ringp != NULL);
1829 REQUIRE(*ringp != NULL);
1834 RWLOCK(&ring->lock, isc_rwlocktype_write);
1835 INSIST(ring->references > 0);
1837 references = ring->references;
1838 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
1840 if (references == 0)
1845 dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) {
1847 isc_result_t result;
1849 isc_stdtime_get(&now);
1851 result = restore_key(ring, now, fp);
1852 if (result == ISC_R_NOMORE)
1854 if (result == DNS_R_BADALG || result == DNS_R_EXPIRED)
1855 result = ISC_R_SUCCESS;
1856 } while (result == ISC_R_SUCCESS);