Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / tsig.c
blobc7f9f27d6c4cb06a4ffd1c2cb8a2da8798294874
1 /* $NetBSD: tsig.c,v 1.8 2015/07/08 17:28:59 christos Exp $ */
3 /*
4 * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2002 Internet Software Consortium.
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.
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.
21 * Id
23 /*! \file */
24 #include <config.h>
25 #include <stdlib.h>
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>
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>
48 #include <dst/result.h>
50 #define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G')
51 #define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)
53 #ifndef DNS_TSIG_MAXGENERATEDKEYS
54 #define DNS_TSIG_MAXGENERATEDKEYS 4096
55 #endif
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)
68 #define BADTIMELEN 6
70 static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";
71 static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };
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}
82 dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
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}
94 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
97 * Since Microsoft doesn't follow its own standard, we will use this
98 * alternate name as a second guess.
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}
110 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
112 static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
113 static unsigned char hmacsha1_offsets[] = { 0, 10 };
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}
124 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
126 static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
127 static unsigned char hmacsha224_offsets[] = { 0, 12 };
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}
138 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
140 static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
141 static unsigned char hmacsha256_offsets[] = { 0, 12 };
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}
152 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
154 static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
155 static unsigned char hmacsha384_offsets[] = { 0, 12 };
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}
166 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
168 static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
169 static unsigned char hmacsha512_offsets[] = { 0, 12 };
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}
180 LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
182 static isc_result_t
183 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
185 static void
186 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
187 ISC_FORMAT_PRINTF(3, 4);
189 static void
190 cleanup_ring(dns_tsig_keyring_t *ring);
191 static void
192 tsigkey_free(dns_tsigkey_t *key);
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];
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>");
208 if (key != NULL && key->generated && key->creator)
209 dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
210 else
211 strcpy(creatorstr, "<null>");
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);
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--;
233 (void)dns_rbt_deletename(tkey->ring->keys, &tkey->name, ISC_FALSE);
236 static void
237 adjust_lru(dns_tsigkey_t *tkey) {
238 if (tkey->generated) {
239 RWLOCK(&tkey->ring->lock, isc_rwlocktype_write);
241 * We may have been removed from the LRU list between
242 * removing the read lock and aquiring the write lock.
244 if (ISC_LINK_LINKED(tkey, link) &&
245 tkey->ring->lru.tail != tkey)
247 ISC_LIST_UNLINK(tkey->ring->lru, tkey, link);
248 ISC_LIST_APPEND(tkey->ring->lru, tkey, link);
250 RWUNLOCK(&tkey->ring->lock, isc_rwlocktype_write);
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.
261 static isc_result_t
262 keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
263 dns_tsigkey_t *tkey)
265 isc_result_t result;
267 RWLOCK(&ring->lock, isc_rwlocktype_write);
268 ring->writecount++;
271 * Do on the fly cleaning. Find some nodes we might not
272 * want around any more.
274 if (ring->writecount > 10) {
275 cleanup_ring(ring);
276 ring->writecount = 0;
279 result = dns_rbt_addname(ring->keys, name, tkey);
280 if (result == ISC_R_SUCCESS && tkey->generated) {
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.
285 ISC_LIST_APPEND(ring->lru, tkey, link);
286 if (ring->generated++ > ring->maxgenerated)
287 remove_fromring(ISC_LIST_HEAD(ring->lru));
289 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
291 return (result);
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)
301 dns_tsigkey_t *tkey;
302 isc_result_t ret;
303 unsigned int refs = 0;
305 REQUIRE(key == NULL || *key == NULL);
306 REQUIRE(name != NULL);
307 REQUIRE(algorithm != NULL);
308 REQUIRE(mctx != NULL);
309 REQUIRE(key != NULL || ring != NULL);
311 tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
312 if (tkey == NULL)
313 return (ISC_R_NOMEMORY);
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);
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;
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;
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;
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;
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;
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;
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;
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;
373 } else {
374 if (dstkey != NULL) {
375 ret = DNS_R_BADALG;
376 goto cleanup_name;
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;
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);
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;
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;
403 } else
404 tkey->creator = NULL;
406 tkey->key = NULL;
407 if (dstkey != NULL)
408 dst_key_attach(dstkey, &tkey->key);
409 tkey->ring = ring;
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;
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);
426 tkey->magic = TSIG_MAGIC;
428 if (ring != NULL) {
429 ret = keyring_add(ring, name, tkey);
430 if (ret != ISC_R_SUCCESS)
431 goto cleanup_refs;
435 * Ignore this if it's a GSS key, since the key size is meaningless.
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);
448 if (key != NULL)
449 *key = tkey;
451 return (ISC_R_SUCCESS);
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));
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));
471 cleanup_name:
472 dns_name_free(&tkey->name, mctx);
473 cleanup_key:
474 isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));
476 return (ret);
480 * Find a few nodes to destroy if possible.
482 static void
483 cleanup_ring(dns_tsig_keyring_t *ring)
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;
495 * Start up a new iterator each time.
497 isc_stdtime_get(&now);
498 dns_name_init(&foundname, NULL);
499 dns_fixedname_init(&fixedorigin);
500 origin = dns_fixedname_name(&fixedorigin);
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;
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;
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;
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));
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);
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;
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);
587 if (isc_serial_lt(expire, now))
588 return (DNS_R_EXPIRED);
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);
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);
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);
614 dstalg = dst_alg_fromname(algorithm);
615 if (dstalg == 0)
616 return (DNS_R_BADALG);
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);
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);
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;
641 REQUIRE(tkey != NULL);
642 REQUIRE(fp != NULL);
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);
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;
669 REQUIRE(ringp != NULL && *ringp != NULL);
671 ring = *ringp;
672 *ringp = NULL;
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);
680 if (references != 0)
681 return (DNS_R_CONTINUE);
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;
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;
711 destroy:
712 destroyring(ring);
713 return (result);
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)
723 dst_key_t *dstkey = NULL;
724 isc_result_t result;
726 REQUIRE(length >= 0);
727 if (length > 0)
728 REQUIRE(secret != NULL);
730 if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
731 if (secret != NULL) {
732 isc_buffer_t b;
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);
744 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
745 if (secret != NULL) {
746 isc_buffer_t b;
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);
758 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
759 if (secret != NULL) {
760 isc_buffer_t b;
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);
772 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
773 if (secret != NULL) {
774 isc_buffer_t b;
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);
786 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
787 if (secret != NULL) {
788 isc_buffer_t b;
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);
800 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
801 if (secret != NULL) {
802 isc_buffer_t b;
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);
814 } else if (length > 0)
815 return (DNS_R_BADALG);
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);
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);
830 isc_refcount_increment(&source->refs, NULL);
831 *targetp = source;
834 static void
835 tsigkey_free(dns_tsigkey_t *key) {
836 REQUIRE(VALID_TSIG_KEY(key));
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));
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));
850 isc_refcount_destroy(&key->refs);
851 isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
854 void
855 dns_tsigkey_detach(dns_tsigkey_t **keyp) {
856 dns_tsigkey_t *key;
857 unsigned int refs;
859 REQUIRE(keyp != NULL);
860 REQUIRE(VALID_TSIG_KEY(*keyp));
862 key = *keyp;
863 isc_refcount_decrement(&key->refs, &refs);
865 if (refs == 0)
866 tsigkey_free(key);
868 *keyp = NULL;
871 void
872 dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
873 REQUIRE(VALID_TSIG_KEY(key));
874 REQUIRE(key->ring != NULL);
876 RWLOCK(&key->ring->lock, isc_rwlocktype_write);
877 remove_fromring(key);
878 RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
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);
901 REQUIRE(msg != NULL);
902 REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg)));
905 * If this is a response, there should be a query tsig.
907 if (response && msg->querytsig == NULL)
908 return (DNS_R_EXPECTEDTSIG);
910 dynbuf = NULL;
912 mctx = msg->mctx;
913 key = dns_message_gettsigkey(msg);
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);
922 isc_stdtime_get(&now);
923 tsig.timesigned = now + msg->timeadjust;
924 tsig.fudge = DNS_TSIG_FUDGE;
926 tsig.originalid = msg->id;
928 isc_buffer_init(&databuf, data, sizeof(data));
930 if (response)
931 tsig.error = msg->querytsigstatus;
932 else
933 tsig.error = dns_rcode_noerror;
935 if (tsig.error != dns_tsigerror_badtime) {
936 tsig.otherlen = 0;
937 tsig.other = NULL;
938 } else {
939 isc_buffer_t otherbuf;
941 tsig.otherlen = BADTIMELEN;
942 tsig.other = badtimedata;
943 isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
944 isc_buffer_putuint48(&otherbuf, tsig.timesigned);
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;
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);
959 * If this is a response, digest the query signature.
961 if (response) {
962 dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
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;
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;
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
994 * Digest the header.
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;
1004 * Digest the remainder of the message.
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;
1012 if (msg->tcp_continuation == 0) {
1014 * Digest the name, class, ttl, alg.
1016 dns_name_toregion(&key->name, &r);
1017 ret = dst_context_adddata(ctx, &r);
1018 if (ret != ISC_R_SUCCESS)
1019 goto cleanup_context;
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;
1029 dns_name_toregion(&tsig.algorithm, &r);
1030 ret = dst_context_adddata(ctx, &r);
1031 if (ret != ISC_R_SUCCESS)
1032 goto cleanup_context;
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;
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;
1048 if (msg->tcp_continuation == 0) {
1050 * Digest the error and other data length.
1052 isc_buffer_clear(&databuf);
1053 isc_buffer_putuint16(&databuf, tsig.error);
1054 isc_buffer_putuint16(&databuf, tsig.otherlen);
1056 isc_buffer_usedregion(&databuf, &r);
1057 ret = dst_context_adddata(ctx, &r);
1058 if (ret != ISC_R_SUCCESS)
1059 goto cleanup_context;
1062 * Digest other data.
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;
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;
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;
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;
1113 dns_message_takebuffer(msg, &dynbuf);
1115 if (tsig.signature != NULL) {
1116 isc_mem_put(mctx, tsig.signature, sigsize);
1117 tsig.signature = NULL;
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;
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;
1148 /* Windows does not like the tsig name being compressed. */
1149 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
1151 return (ISC_R_SUCCESS);
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);
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)
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;
1193 REQUIRE(source != NULL);
1194 REQUIRE(DNS_MESSAGE_VALID(msg));
1195 tsigkey = dns_message_gettsigkey(msg);
1196 response = is_response(msg);
1198 REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
1200 msg->verify_attempted = 1;
1202 if (msg->tcp_continuation) {
1203 if (tsigkey == NULL || msg->querytsig == NULL)
1204 return (DNS_R_UNEXPECTEDTSIG);
1205 return (tsig_verify_tcp(source, msg));
1209 * There should be a TSIG record...
1211 if (msg->tsig == NULL)
1212 return (DNS_R_EXPECTEDTSIG);
1215 * If this is a response and there's no key or query TSIG, there
1216 * shouldn't be one on the response.
1218 if (response && (tsigkey == NULL || msg->querytsig == NULL))
1219 return (DNS_R_UNEXPECTEDTSIG);
1221 mctx = msg->mctx;
1224 * If we're here, we know the message is well formed and contains a
1225 * TSIG record.
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);
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
1255 * Do the key name and algorithm match that of the query?
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);
1267 * Get the current time.
1269 isc_stdtime_get(&now);
1272 * Find dns_tsigkey_t based on keyname.
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);
1293 msg->tsigkey = tsigkey;
1296 key = tsigkey->key;
1299 * Is the time ok?
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);
1312 * Check digest length.
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);
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);
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);
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);
1347 if (tsig.siglen > 0) {
1348 sig_r.base = tsig.signature;
1349 sig_r.length = tsig.siglen;
1351 ret = dst_context_create3(key, mctx,
1352 DNS_LOGCATEGORY_DNSSEC,
1353 ISC_FALSE, &ctx);
1354 if (ret != ISC_R_SUCCESS)
1355 return (ret);
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;
1374 * Extract the header.
1376 isc_buffer_usedregion(source, &r);
1377 memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
1378 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1381 * Decrement the additional field counter.
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);
1388 * Put in the original id.
1390 id = htons(tsig.originalid);
1391 memmove(&header[0], &id, 2);
1394 * Digest the modified header.
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;
1403 * Digest all non-TSIG records.
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;
1413 * Digest the key name.
1415 dns_name_toregion(&tsigkey->name, &r);
1416 ret = dst_context_adddata(ctx, &r);
1417 if (ret != ISC_R_SUCCESS)
1418 goto cleanup_context;
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;
1429 * Digest the key algorithm.
1431 dns_name_toregion(tsigkey->algorithm, &r);
1432 ret = dst_context_adddata(ctx, &r);
1433 if (ret != ISC_R_SUCCESS)
1434 goto cleanup_context;
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;
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;
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;
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);
1472 msg->tsigstatus = dns_rcode_noerror;
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);
1481 msg->verified_sig = 1;
1483 return (ISC_R_SUCCESS);
1485 cleanup_context:
1486 if (ctx != NULL)
1487 dst_context_destroy(&ctx);
1489 return (ret);
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;
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);
1515 if (!is_response(msg))
1516 return (DNS_R_EXPECTEDRESPONSE);
1518 mctx = msg->mctx;
1520 tsigkey = dns_message_gettsigkey(msg);
1523 * Extract and parse the previous TSIG
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);
1535 * If there is a TSIG in this message, do some checks.
1537 if (msg->tsig != NULL) {
1538 has_tsig = ISC_TRUE;
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;
1550 * Do the key name and algorithm match that of the query?
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;
1562 * Is the time ok?
1564 isc_stdtime_get(&now);
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;
1581 key = tsigkey->key;
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;
1591 * Digest the length of the query signature
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;
1601 * Digest the data of the query signature
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;
1613 * Extract the header.
1615 isc_buffer_usedregion(source, &r);
1616 memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
1617 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1620 * Decrement the additional field counter if necessary.
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);
1629 * Put in the original id.
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);
1638 * Digest the modified header.
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;
1647 * Digest all non-TSIG records.
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;
1660 * Digest the time signed and fudge.
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;
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;
1684 goto cleanup_context;
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;
1695 else if (ret != ISC_R_SUCCESS)
1696 goto cleanup_context;
1698 dst_context_destroy(&msg->tsigctx);
1701 msg->tsigstatus = dns_rcode_noerror;
1702 return (ISC_R_SUCCESS);
1704 cleanup_context:
1705 dst_context_destroy(&msg->tsigctx);
1707 cleanup_querystruct:
1708 dns_rdata_freestruct(&querytsig);
1710 return (ret);
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)
1718 dns_tsigkey_t *key;
1719 isc_stdtime_t now;
1720 isc_result_t result;
1722 REQUIRE(tsigkey != NULL);
1723 REQUIRE(*tsigkey == NULL);
1724 REQUIRE(name != NULL);
1725 REQUIRE(ring != NULL);
1727 RWLOCK(&ring->lock, isc_rwlocktype_write);
1728 cleanup_ring(ring);
1729 RWUNLOCK(&ring->lock, isc_rwlocktype_write);
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);
1739 if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
1740 RWUNLOCK(&ring->lock, isc_rwlocktype_read);
1741 return (ISC_R_NOTFOUND);
1743 if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
1745 * The key has expired.
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);
1753 #if 0
1755 * MPAXXX We really should look at the inception time.
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);
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);
1771 static void
1772 free_tsignode(void *node, void *_unused) {
1773 dns_tsigkey_t *key;
1775 REQUIRE(node != NULL);
1777 UNUSED(_unused);
1779 key = node;
1780 if (key->generated) {
1781 if (ISC_LINK_LINKED(key, link))
1782 ISC_LIST_UNLINK(key->ring->lru, key, link);
1784 dns_tsigkey_detach(&key);
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;
1792 REQUIRE(mctx != NULL);
1793 REQUIRE(ringp != NULL);
1794 REQUIRE(*ringp == NULL);
1796 ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
1797 if (ring == NULL)
1798 return (ISC_R_NOMEMORY);
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);
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);
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;
1822 *ringp = ring;
1823 return (ISC_R_SUCCESS);
1826 isc_result_t
1827 dns_tsigkeyring_add(dns_tsig_keyring_t *ring, dns_name_t *name,
1828 dns_tsigkey_t *tkey)
1830 isc_result_t result;
1832 result = keyring_add(ring, name, tkey);
1833 if (result == ISC_R_SUCCESS)
1834 isc_refcount_increment(&tkey->refs, NULL);
1836 return (result);
1839 void
1840 dns_tsigkeyring_attach(dns_tsig_keyring_t *source, dns_tsig_keyring_t **target)
1842 REQUIRE(source != NULL);
1843 REQUIRE(target != NULL && *target == NULL);
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);
1853 void
1854 dns_tsigkeyring_detach(dns_tsig_keyring_t **ringp) {
1855 dns_tsig_keyring_t *ring;
1856 unsigned int references;
1858 REQUIRE(ringp != NULL);
1859 REQUIRE(*ringp != NULL);
1861 ring = *ringp;
1862 *ringp = NULL;
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);
1870 if (references == 0)
1871 destroyring(ring);
1874 void
1875 dns_keyring_restore(dns_tsig_keyring_t *ring, FILE *fp) {
1876 isc_stdtime_t now;
1877 isc_result_t result;
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);