1 /* $NetBSD: tsig.c,v 1.8 2015/07/08 17:28:59 christos Exp $ */
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.
27 #include <isc/buffer.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?) */
36 #include <dns/keyvalues.h>
38 #include <dns/message.h>
39 #include <dns/fixedname.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>
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
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)
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
= {
76 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
77 hmacmd5_offsets
, NULL
,
78 {(void *)-1, (void *)-1},
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
= {
89 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
90 gsstsig_offsets
, NULL
,
91 {(void *)-1, (void *)-1},
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
= {
104 gsstsigms_ndata
, 19, 4,
105 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
106 gsstsigms_offsets
, NULL
,
107 {(void *)-1, (void *)-1},
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
= {
117 hmacsha1_ndata
, 11, 2,
118 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
119 hmacsha1_offsets
, NULL
,
120 {(void *)-1, (void *)-1},
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
= {
131 hmacsha224_ndata
, 13, 2,
132 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
133 hmacsha224_offsets
, NULL
,
134 {(void *)-1, (void *)-1},
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
= {
145 hmacsha256_ndata
, 13, 2,
146 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
147 hmacsha256_offsets
, NULL
,
148 {(void *)-1, (void *)-1},
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
= {
159 hmacsha384_ndata
, 13, 2,
160 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
161 hmacsha384_offsets
, NULL
,
162 {(void *)-1, (void *)-1},
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
= {
173 hmacsha512_ndata
, 13, 2,
174 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
175 hmacsha512_offsets
, NULL
,
176 {(void *)-1, (void *)-1},
180 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_tsig_hmacsha512_name
= &hmacsha512
;
183 tsig_verify_tcp(isc_buffer_t
*source
, dns_message_t
*msg
);
186 tsig_log(dns_tsigkey_t
*key
, int level
, const char *fmt
, ...)
187 ISC_FORMAT_PRINTF(3, 4);
190 cleanup_ring(dns_tsig_keyring_t
*ring
);
192 tsigkey_free(dns_tsigkey_t
*key
);
195 tsig_log(dns_tsigkey_t
*key
, int level
, const char *fmt
, ...) {
198 char namestr
[DNS_NAME_FORMATSIZE
];
199 char creatorstr
[DNS_NAME_FORMATSIZE
];
201 if (isc_log_wouldlog(dns_lctx
, level
) == ISC_FALSE
)
204 dns_name_format(&key
->name
, namestr
, sizeof(namestr
));
206 strcpy(namestr
, "<null>");
208 if (key
!= NULL
&& key
->generated
&& key
->creator
)
209 dns_name_format(key
->creator
, creatorstr
, sizeof(creatorstr
));
211 strcpy(creatorstr
, "<null>");
214 vsnprintf(message
, sizeof(message
), fmt
, 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
);
222 isc_log_write(dns_lctx
,
223 DNS_LOGCATEGORY_DNSSEC
, DNS_LOGMODULE_TSIG
,
224 level
, "tsig key '%s': %s", namestr
, message
);
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
);
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.
262 keyring_add(dns_tsig_keyring_t
*ring
, dns_name_t
*name
,
267 RWLOCK(&ring
->lock
, isc_rwlocktype_write
);
271 * Do on the fly cleaning. Find some nodes we might not
272 * want around any more.
274 if (ring
->writecount
> 10) {
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
);
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
)
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
));
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
)
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
374 if (dstkey
!= NULL
) {
378 tkey
->algorithm
= isc_mem_get(mctx
, sizeof(dns_name_t
));
379 if (tkey
->algorithm
== NULL
) {
380 ret
= ISC_R_NOMEMORY
;
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
,
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
;
404 tkey
->creator
= NULL
;
408 dst_key_attach(dstkey
, &tkey
->key
);
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
;
423 isc_mem_attach(mctx
, &tkey
->mctx
);
424 ISC_LINK_INIT(tkey
, link
);
426 tkey
->magic
= TSIG_MAGIC
;
429 ret
= keyring_add(ring
, name
, tkey
);
430 if (ret
!= ISC_R_SUCCESS
)
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",
451 return (ISC_R_SUCCESS
);
456 isc_refcount_decrement(&tkey
->refs
, NULL
);
457 isc_refcount_destroy(&tkey
->refs
);
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
));
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
));
472 dns_name_free(&tkey
->name
, mctx
);
474 isc_mem_put(mctx
, tkey
, sizeof(dns_tsigkey_t
));
480 * Find a few nodes to destroy if possible.
483 cleanup_ring(dns_tsig_keyring_t
*ring
)
486 dns_rbtnodechain_t chain
;
487 dns_name_t foundname
;
488 dns_fixedname_t fixedorigin
;
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
);
503 dns_rbtnodechain_init(&chain
, ring
->mctx
);
504 result
= dns_rbtnodechain_first(&chain
, ring
->keys
, &foundname
,
506 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_NEWORIGIN
) {
507 dns_rbtnodechain_invalidate(&chain
);
513 dns_rbtnodechain_current(&chain
, &foundname
, origin
, &node
);
517 && isc_refcount_current(&tkey
->refs
) == 1
518 && tkey
->inception
!= tkey
->expire
519 && tkey
->expire
< now
) {
520 tsig_log(tkey
, 2, "tsig expire: deleting");
522 dns_rbtnodechain_invalidate(&chain
);
523 remove_fromring(tkey
);
527 result
= dns_rbtnodechain_next(&chain
, &foundname
,
529 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_NEWORIGIN
) {
530 dns_rbtnodechain_invalidate(&chain
);
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
));
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
);
566 restore_key(dns_tsig_keyring_t
*ring
, isc_stdtime_t now
, FILE *fp
) {
567 dst_key_t
*dstkey
= NULL
;
569 char creatorstr
[1024];
570 char algorithmstr
[1024];
572 unsigned int inception
, expire
;
575 dns_name_t
*name
, *creator
, *algorithm
;
576 dns_fixedname_t fname
, fcreator
, falgorithm
;
580 n
= fscanf(fp
, "%1023s %1023s %u %u %1023s %4095s\n", namestr
,
581 creatorstr
, &inception
, &expire
, algorithmstr
, keystr
);
583 return (ISC_R_NOMORE
);
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
)
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
)
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
)
614 dstalg
= dst_alg_fromname(algorithm
);
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
)
624 result
= dns_tsigkey_createfromkey(name
, algorithm
, dstkey
,
625 ISC_TRUE
, creator
, inception
,
626 expire
, ring
->mctx
, ring
, NULL
);
628 dst_key_free(&dstkey
);
633 dump_key(dns_tsigkey_t
*tkey
, FILE *fp
) {
636 char namestr
[DNS_NAME_FORMATSIZE
];
637 char creatorstr
[DNS_NAME_FORMATSIZE
];
638 char algorithmstr
[DNS_NAME_FORMATSIZE
];
641 REQUIRE(tkey
!= 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
,
653 isc_mem_put(tkey
->mctx
, buffer
, length
);
657 dns_tsigkeyring_dumpanddetach(dns_tsig_keyring_t
**ringp
, FILE *fp
) {
659 dns_rbtnodechain_t chain
;
660 dns_name_t foundname
;
661 dns_fixedname_t fixedorigin
;
666 dns_tsig_keyring_t
*ring
;
667 unsigned int references
;
669 REQUIRE(ringp
!= NULL
&& *ringp
!= NULL
);
674 RWLOCK(&ring
->lock
, isc_rwlocktype_write
);
675 INSIST(ring
->references
> 0);
677 references
= ring
->references
;
678 RWUNLOCK(&ring
->lock
, isc_rwlocktype_write
);
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
,
690 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_NEWORIGIN
) {
691 dns_rbtnodechain_invalidate(&chain
);
697 dns_rbtnodechain_current(&chain
, &foundname
, origin
, &node
);
699 if (tkey
!= NULL
&& tkey
->generated
&& tkey
->expire
>= now
)
701 result
= dns_rbtnodechain_next(&chain
, &foundname
,
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
;
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
;
726 REQUIRE(length
>= 0);
728 REQUIRE(secret
!= NULL
);
730 if (dns_name_equal(algorithm
, DNS_TSIG_HMACMD5_NAME
)) {
731 if (secret
!= NULL
) {
734 isc_buffer_init(&b
, secret
, length
);
735 isc_buffer_add(&b
, length
);
736 result
= dst_key_frombuffer(name
, DST_ALG_HMACMD5
,
741 if (result
!= ISC_R_SUCCESS
)
744 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA1_NAME
)) {
745 if (secret
!= NULL
) {
748 isc_buffer_init(&b
, secret
, length
);
749 isc_buffer_add(&b
, length
);
750 result
= dst_key_frombuffer(name
, DST_ALG_HMACSHA1
,
755 if (result
!= ISC_R_SUCCESS
)
758 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA224_NAME
)) {
759 if (secret
!= NULL
) {
762 isc_buffer_init(&b
, secret
, length
);
763 isc_buffer_add(&b
, length
);
764 result
= dst_key_frombuffer(name
, DST_ALG_HMACSHA224
,
769 if (result
!= ISC_R_SUCCESS
)
772 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA256_NAME
)) {
773 if (secret
!= NULL
) {
776 isc_buffer_init(&b
, secret
, length
);
777 isc_buffer_add(&b
, length
);
778 result
= dst_key_frombuffer(name
, DST_ALG_HMACSHA256
,
783 if (result
!= ISC_R_SUCCESS
)
786 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA384_NAME
)) {
787 if (secret
!= NULL
) {
790 isc_buffer_init(&b
, secret
, length
);
791 isc_buffer_add(&b
, length
);
792 result
= dst_key_frombuffer(name
, DST_ALG_HMACSHA384
,
797 if (result
!= ISC_R_SUCCESS
)
800 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA512_NAME
)) {
801 if (secret
!= NULL
) {
804 isc_buffer_init(&b
, secret
, length
);
805 isc_buffer_add(&b
, length
);
806 result
= dst_key_frombuffer(name
, DST_ALG_HMACSHA512
,
811 if (result
!= ISC_R_SUCCESS
)
814 } else if (length
> 0)
815 return (DNS_R_BADALG
);
817 result
= dns_tsigkey_createfromkey(name
, algorithm
, dstkey
,
819 inception
, expire
, mctx
, ring
, key
);
821 dst_key_free(&dstkey
);
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
);
835 tsigkey_free(dns_tsigkey_t
*key
) {
836 REQUIRE(VALID_TSIG_KEY(key
));
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
));
855 dns_tsigkey_detach(dns_tsigkey_t
**keyp
) {
859 REQUIRE(keyp
!= NULL
);
860 REQUIRE(VALID_TSIG_KEY(*keyp
));
863 isc_refcount_decrement(&key
->refs
, &refs
);
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
);
882 dns_tsig_sign(dns_message_t
*msg
) {
884 dns_rdata_any_tsig_t tsig
, querytsig
;
885 unsigned char data
[128];
886 isc_buffer_t databuf
, sigbuf
;
887 isc_buffer_t
*dynbuf
;
889 dns_rdata_t
*rdata
= NULL
;
890 dns_rdatalist_t
*datalist
;
891 dns_rdataset_t
*dataset
;
895 dst_context_t
*ctx
= NULL
;
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
);
913 key
= dns_message_gettsigkey(msg
);
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
));
931 tsig
.error
= msg
->querytsigstatus
;
933 tsig
.error
= dns_rcode_noerror
;
935 if (tsig
.error
!= dns_tsigerror_badtime
) {
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
,
955 if (ret
!= ISC_R_SUCCESS
)
959 * If this is a response, digest the query signature.
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
,
970 if (ret
!= ISC_R_SUCCESS
)
971 goto cleanup_context
;
972 isc_buffer_putuint16(&databuf
, querytsig
.siglen
);
973 if (isc_buffer_availablelength(&databuf
) <
976 goto cleanup_context
;
978 isc_buffer_putmem(&databuf
, querytsig
.signature
,
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
));
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
) {
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
;
1096 tsig
.siglen
= isc_buffer_usedlength(&sigbuf
);
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
)
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
;
1121 ret
= dns_message_gettempname(msg
, &owner
);
1122 if (ret
!= ISC_R_SUCCESS
)
1124 dns_name_init(owner
, NULL
);
1125 ret
= dns_name_dup(&key
->name
, msg
->mctx
, owner
);
1126 if (ret
!= ISC_R_SUCCESS
)
1130 ret
= dns_message_gettemprdatalist(msg
, &datalist
);
1131 if (ret
!= ISC_R_SUCCESS
)
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;
1141 ISC_LIST_INIT(datalist
->rdata
);
1142 ISC_LIST_APPEND(datalist
->rdata
, rdata
, link
);
1143 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist
, dataset
)
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
);
1154 dns_message_puttemprdatalist(msg
, &datalist
);
1156 dns_message_puttempname(msg
, &owner
);
1159 isc_buffer_free(&dynbuf
);
1161 dns_message_puttemprdata(msg
, &rdata
);
1163 if (tsig
.signature
!= NULL
)
1164 isc_mem_put(mctx
, tsig
.signature
, sigsize
);
1167 dst_context_destroy(&ctx
);
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
;
1183 dns_tsigkey_t
*tsigkey
;
1184 dst_key_t
*key
= NULL
;
1185 unsigned char header
[DNS_MESSAGE_HEADERLEN
];
1186 dst_context_t
*ctx
= NULL
;
1188 isc_uint16_t addcount
, id
;
1189 unsigned int siglen
;
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
);
1224 * If we're here, we know the message is well formed and contains a
1228 keyname
= msg
->tsigname
;
1229 ret
= dns_rdataset_first(msg
->tsig
);
1230 if (ret
!= ISC_R_SUCCESS
)
1232 dns_rdataset_current(msg
->tsig
, &rdata
);
1233 ret
= dns_rdata_tostruct(&rdata
, &tsig
, NULL
);
1234 if (ret
!= ISC_R_SUCCESS
)
1236 dns_rdata_reset(&rdata
);
1238 ret
= dns_rdataset_first(msg
->querytsig
);
1239 if (ret
!= ISC_R_SUCCESS
)
1241 dns_rdataset_current(msg
->querytsig
, &rdata
);
1242 ret
= dns_rdata_tostruct(&rdata
, &querytsig
, NULL
);
1243 if (ret
!= ISC_R_SUCCESS
)
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
));
1255 * Do the key name and algorithm match that of the query?
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
;
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
,
1287 mctx
, NULL
, &msg
->tsigkey
);
1288 if (ret
!= ISC_R_SUCCESS
)
1290 tsig_log(msg
->tsigkey
, 2, "unknown key");
1291 return (DNS_R_TSIGVERIFYFAILURE
);
1293 msg
->tsigkey
= tsigkey
;
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
)
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
,
1354 if (ret
!= ISC_R_SUCCESS
)
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
);
1478 return (DNS_R_TSIGERRORSET
);
1481 msg
->verified_sig
= 1;
1483 return (ISC_R_SUCCESS
);
1487 dst_context_destroy(&ctx
);
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
;
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
;
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
);
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
)
1528 dns_rdataset_current(msg
->querytsig
, &rdata
);
1529 ret
= dns_rdata_tostruct(&rdata
, &querytsig
, NULL
);
1530 if (ret
!= ISC_R_SUCCESS
)
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
;
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
;
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.
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? */
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
;
1652 r
.length
= msg
->sigstart
- DNS_MESSAGE_HEADERLEN
;
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.
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
;
1678 ret
= DNS_R_TSIGERRORSET
;
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
);
1705 dst_context_destroy(&msg
->tsigctx
);
1707 cleanup_querystruct
:
1708 dns_rdata_freestruct(&querytsig
);
1715 dns_tsigkey_find(dns_tsigkey_t
**tsigkey
, dns_name_t
*name
,
1716 dns_name_t
*algorithm
, dns_tsig_keyring_t
*ring
)
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
);
1729 RWUNLOCK(&ring
->lock
, isc_rwlocktype_write
);
1731 isc_stdtime_get(&now
);
1732 RWLOCK(&ring
->lock
, isc_rwlocktype_read
);
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
);
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
);
1761 return (ISC_R_NOTFOUND
);
1764 isc_refcount_increment(&key
->refs
, NULL
);
1765 RWUNLOCK(&ring
->lock
, isc_rwlocktype_read
);
1768 return (ISC_R_SUCCESS
);
1772 free_tsignode(void *node
, void *_unused
) {
1775 REQUIRE(node
!= NULL
);
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
);
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
));
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
));
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
));
1814 ring
->writecount
= 0;
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;
1823 return (ISC_R_SUCCESS
);
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
);
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);
1850 RWUNLOCK(&source
->lock
, isc_rwlocktype_write
);
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
);
1864 RWLOCK(&ring
->lock
, isc_rwlocktype_write
);
1865 INSIST(ring
->references
> 0);
1867 references
= ring
->references
;
1868 RWUNLOCK(&ring
->lock
, isc_rwlocktype_write
);
1870 if (references
== 0)
1875 dns_keyring_restore(dns_tsig_keyring_t
*ring
, FILE *fp
) {
1877 isc_result_t result
;
1879 isc_stdtime_get(&now
);
1881 result
= restore_key(ring
, now
, fp
);
1882 if (result
== ISC_R_NOMORE
)
1884 if (result
== DNS_R_BADALG
|| result
== DNS_R_EXPIRED
)
1885 result
= ISC_R_SUCCESS
;
1886 } while (result
== ISC_R_SUCCESS
);