4 * Copyright (C) 2004-2009 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: tsig.c,v 1.138 2009/06/11 23:47:55 tbox Exp
27 #include <isc/buffer.h>
29 #include <isc/print.h>
30 #include <isc/refcount.h>
31 #include <isc/string.h> /* Required for HP/UX (and others?) */
35 #include <dns/keyvalues.h>
37 #include <dns/message.h>
38 #include <dns/fixedname.h>
40 #include <dns/rdata.h>
41 #include <dns/rdatalist.h>
42 #include <dns/rdataset.h>
43 #include <dns/rdatastruct.h>
44 #include <dns/result.h>
47 #include <dst/result.h>
49 #define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G')
50 #define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)
52 #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
53 #define algname_is_allocated(algname) \
54 ((algname) != dns_tsig_hmacmd5_name && \
55 (algname) != dns_tsig_hmacsha1_name && \
56 (algname) != dns_tsig_hmacsha224_name && \
57 (algname) != dns_tsig_hmacsha256_name && \
58 (algname) != dns_tsig_hmacsha384_name && \
59 (algname) != dns_tsig_hmacsha512_name && \
60 (algname) != dns_tsig_gssapi_name && \
61 (algname) != dns_tsig_gssapims_name)
65 static unsigned char hmacmd5_ndata
[] = "\010hmac-md5\007sig-alg\003reg\003int";
66 static unsigned char hmacmd5_offsets
[] = { 0, 9, 17, 21, 25 };
68 static dns_name_t hmacmd5
= {
71 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
72 hmacmd5_offsets
, NULL
,
73 {(void *)-1, (void *)-1},
77 dns_name_t
*dns_tsig_hmacmd5_name
= &hmacmd5
;
79 static unsigned char gsstsig_ndata
[] = "\010gss-tsig";
80 static unsigned char gsstsig_offsets
[] = { 0, 9 };
81 static dns_name_t gsstsig
= {
84 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
85 gsstsig_offsets
, NULL
,
86 {(void *)-1, (void *)-1},
89 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_tsig_gssapi_name
= &gsstsig
;
92 * Since Microsoft doesn't follow its own standard, we will use this
93 * alternate name as a second guess.
95 static unsigned char gsstsigms_ndata
[] = "\003gss\011microsoft\003com";
96 static unsigned char gsstsigms_offsets
[] = { 0, 4, 14, 18 };
97 static dns_name_t gsstsigms
= {
99 gsstsigms_ndata
, 19, 4,
100 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
101 gsstsigms_offsets
, NULL
,
102 {(void *)-1, (void *)-1},
105 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_tsig_gssapims_name
= &gsstsigms
;
107 static unsigned char hmacsha1_ndata
[] = "\011hmac-sha1";
108 static unsigned char hmacsha1_offsets
[] = { 0, 10 };
110 static dns_name_t hmacsha1
= {
112 hmacsha1_ndata
, 11, 2,
113 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
114 hmacsha1_offsets
, NULL
,
115 {(void *)-1, (void *)-1},
119 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_tsig_hmacsha1_name
= &hmacsha1
;
121 static unsigned char hmacsha224_ndata
[] = "\013hmac-sha224";
122 static unsigned char hmacsha224_offsets
[] = { 0, 12 };
124 static dns_name_t hmacsha224
= {
126 hmacsha224_ndata
, 13, 2,
127 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
128 hmacsha224_offsets
, NULL
,
129 {(void *)-1, (void *)-1},
133 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_tsig_hmacsha224_name
= &hmacsha224
;
135 static unsigned char hmacsha256_ndata
[] = "\013hmac-sha256";
136 static unsigned char hmacsha256_offsets
[] = { 0, 12 };
138 static dns_name_t hmacsha256
= {
140 hmacsha256_ndata
, 13, 2,
141 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
142 hmacsha256_offsets
, NULL
,
143 {(void *)-1, (void *)-1},
147 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_tsig_hmacsha256_name
= &hmacsha256
;
149 static unsigned char hmacsha384_ndata
[] = "\013hmac-sha384";
150 static unsigned char hmacsha384_offsets
[] = { 0, 12 };
152 static dns_name_t hmacsha384
= {
154 hmacsha384_ndata
, 13, 2,
155 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
156 hmacsha384_offsets
, NULL
,
157 {(void *)-1, (void *)-1},
161 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_tsig_hmacsha384_name
= &hmacsha384
;
163 static unsigned char hmacsha512_ndata
[] = "\013hmac-sha512";
164 static unsigned char hmacsha512_offsets
[] = { 0, 12 };
166 static dns_name_t hmacsha512
= {
168 hmacsha512_ndata
, 13, 2,
169 DNS_NAMEATTR_READONLY
| DNS_NAMEATTR_ABSOLUTE
,
170 hmacsha512_offsets
, NULL
,
171 {(void *)-1, (void *)-1},
175 LIBDNS_EXTERNAL_DATA dns_name_t
*dns_tsig_hmacsha512_name
= &hmacsha512
;
178 tsig_verify_tcp(isc_buffer_t
*source
, dns_message_t
*msg
);
181 tsig_log(dns_tsigkey_t
*key
, int level
, const char *fmt
, ...)
182 ISC_FORMAT_PRINTF(3, 4);
185 cleanup_ring(dns_tsig_keyring_t
*ring
);
187 tsigkey_free(dns_tsigkey_t
*key
);
190 tsig_log(dns_tsigkey_t
*key
, int level
, const char *fmt
, ...) {
193 char namestr
[DNS_NAME_FORMATSIZE
];
194 char creatorstr
[DNS_NAME_FORMATSIZE
];
196 if (isc_log_wouldlog(dns_lctx
, level
) == ISC_FALSE
)
199 dns_name_format(&key
->name
, namestr
, sizeof(namestr
));
201 strcpy(namestr
, "<null>");
203 if (key
!= NULL
&& key
->generated
)
204 dns_name_format(key
->creator
, creatorstr
, sizeof(creatorstr
));
207 vsnprintf(message
, sizeof(message
), fmt
, ap
);
209 if (key
!= NULL
&& key
->generated
)
210 isc_log_write(dns_lctx
,
211 DNS_LOGCATEGORY_DNSSEC
, DNS_LOGMODULE_TSIG
,
212 level
, "tsig key '%s' (%s): %s",
213 namestr
, creatorstr
, message
);
215 isc_log_write(dns_lctx
,
216 DNS_LOGCATEGORY_DNSSEC
, DNS_LOGMODULE_TSIG
,
217 level
, "tsig key '%s': %s", namestr
, message
);
221 * A supplemental routine just to add a key to ring. Note that reference
222 * counter should be counted separately because we may be adding the key
223 * as part of creation of the key, in which case the reference counter was
224 * already initialized. Also note we don't need RWLOCK for the reference
225 * counter: it's protected by a separate lock.
228 keyring_add(dns_tsig_keyring_t
*ring
, dns_name_t
*name
,
233 RWLOCK(&ring
->lock
, isc_rwlocktype_write
);
237 * Do on the fly cleaning. Find some nodes we might not
238 * want around any more.
240 if (ring
->writecount
> 10) {
242 ring
->writecount
= 0;
245 result
= dns_rbt_addname(ring
->keys
, name
, tkey
);
246 RWUNLOCK(&ring
->lock
, isc_rwlocktype_write
);
252 dns_tsigkey_createfromkey(dns_name_t
*name
, dns_name_t
*algorithm
,
253 dst_key_t
*dstkey
, isc_boolean_t generated
,
254 dns_name_t
*creator
, isc_stdtime_t inception
,
255 isc_stdtime_t expire
, isc_mem_t
*mctx
,
256 dns_tsig_keyring_t
*ring
, dns_tsigkey_t
**key
)
260 unsigned int refs
= 0;
262 REQUIRE(key
== NULL
|| *key
== NULL
);
263 REQUIRE(name
!= NULL
);
264 REQUIRE(algorithm
!= NULL
);
265 REQUIRE(mctx
!= NULL
);
266 REQUIRE(key
!= NULL
|| ring
!= NULL
);
268 tkey
= (dns_tsigkey_t
*) isc_mem_get(mctx
, sizeof(dns_tsigkey_t
));
270 return (ISC_R_NOMEMORY
);
272 dns_name_init(&tkey
->name
, NULL
);
273 ret
= dns_name_dup(name
, mctx
, &tkey
->name
);
274 if (ret
!= ISC_R_SUCCESS
)
276 (void)dns_name_downcase(&tkey
->name
, &tkey
->name
, NULL
);
278 if (dns_name_equal(algorithm
, DNS_TSIG_HMACMD5_NAME
)) {
279 tkey
->algorithm
= DNS_TSIG_HMACMD5_NAME
;
280 if (dstkey
!= NULL
&& dst_key_alg(dstkey
) != DST_ALG_HMACMD5
) {
284 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA1_NAME
)) {
285 tkey
->algorithm
= DNS_TSIG_HMACSHA1_NAME
;
286 if (dstkey
!= NULL
&& dst_key_alg(dstkey
) != DST_ALG_HMACSHA1
) {
290 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA224_NAME
)) {
291 tkey
->algorithm
= DNS_TSIG_HMACSHA224_NAME
;
292 if (dstkey
!= NULL
&&
293 dst_key_alg(dstkey
) != DST_ALG_HMACSHA224
) {
297 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA256_NAME
)) {
298 tkey
->algorithm
= DNS_TSIG_HMACSHA256_NAME
;
299 if (dstkey
!= NULL
&&
300 dst_key_alg(dstkey
) != DST_ALG_HMACSHA256
) {
304 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA384_NAME
)) {
305 tkey
->algorithm
= DNS_TSIG_HMACSHA384_NAME
;
306 if (dstkey
!= NULL
&&
307 dst_key_alg(dstkey
) != DST_ALG_HMACSHA384
) {
311 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA512_NAME
)) {
312 tkey
->algorithm
= DNS_TSIG_HMACSHA512_NAME
;
313 if (dstkey
!= NULL
&&
314 dst_key_alg(dstkey
) != DST_ALG_HMACSHA512
) {
318 } else if (dns_name_equal(algorithm
, DNS_TSIG_GSSAPI_NAME
)) {
319 tkey
->algorithm
= DNS_TSIG_GSSAPI_NAME
;
320 if (dstkey
!= NULL
&& dst_key_alg(dstkey
) != DST_ALG_GSSAPI
) {
324 } else if (dns_name_equal(algorithm
, DNS_TSIG_GSSAPIMS_NAME
)) {
325 tkey
->algorithm
= DNS_TSIG_GSSAPIMS_NAME
;
326 if (dstkey
!= NULL
&& dst_key_alg(dstkey
) != DST_ALG_GSSAPI
) {
331 if (dstkey
!= NULL
) {
335 tkey
->algorithm
= isc_mem_get(mctx
, sizeof(dns_name_t
));
336 if (tkey
->algorithm
== NULL
) {
337 ret
= ISC_R_NOMEMORY
;
340 dns_name_init(tkey
->algorithm
, NULL
);
341 ret
= dns_name_dup(algorithm
, mctx
, tkey
->algorithm
);
342 if (ret
!= ISC_R_SUCCESS
)
343 goto cleanup_algorithm
;
344 (void)dns_name_downcase(tkey
->algorithm
, tkey
->algorithm
,
348 if (creator
!= NULL
) {
349 tkey
->creator
= isc_mem_get(mctx
, sizeof(dns_name_t
));
350 if (tkey
->creator
== NULL
) {
351 ret
= ISC_R_NOMEMORY
;
352 goto cleanup_algorithm
;
354 dns_name_init(tkey
->creator
, NULL
);
355 ret
= dns_name_dup(creator
, mctx
, tkey
->creator
);
356 if (ret
!= ISC_R_SUCCESS
) {
357 isc_mem_put(mctx
, tkey
->creator
, sizeof(dns_name_t
));
358 goto cleanup_algorithm
;
361 tkey
->creator
= NULL
;
370 ret
= isc_refcount_init(&tkey
->refs
, refs
);
371 if (ret
!= ISC_R_SUCCESS
)
372 goto cleanup_creator
;
374 tkey
->generated
= generated
;
375 tkey
->inception
= inception
;
376 tkey
->expire
= expire
;
378 isc_mem_attach(mctx
, &tkey
->mctx
);
380 tkey
->magic
= TSIG_MAGIC
;
383 ret
= keyring_add(ring
, name
, tkey
);
384 if (ret
!= ISC_R_SUCCESS
)
389 * Ignore this if it's a GSS key, since the key size is meaningless.
391 if (dstkey
!= NULL
&& dst_key_size(dstkey
) < 64 &&
392 !dns_name_equal(algorithm
, DNS_TSIG_GSSAPI_NAME
) &&
393 !dns_name_equal(algorithm
, DNS_TSIG_GSSAPIMS_NAME
)) {
394 char namestr
[DNS_NAME_FORMATSIZE
];
395 dns_name_format(name
, namestr
, sizeof(namestr
));
396 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_DNSSEC
,
397 DNS_LOGMODULE_TSIG
, ISC_LOG_INFO
,
398 "the key '%s' is too short to be secure",
405 return (ISC_R_SUCCESS
);
410 isc_refcount_decrement(&tkey
->refs
, NULL
);
411 isc_refcount_destroy(&tkey
->refs
);
413 if (tkey
->creator
!= NULL
) {
414 dns_name_free(tkey
->creator
, mctx
);
415 isc_mem_put(mctx
, tkey
->creator
, sizeof(dns_name_t
));
418 if (algname_is_allocated(tkey
->algorithm
)) {
419 if (dns_name_dynamic(tkey
->algorithm
))
420 dns_name_free(tkey
->algorithm
, mctx
);
421 isc_mem_put(mctx
, tkey
->algorithm
, sizeof(dns_name_t
));
424 dns_name_free(&tkey
->name
, mctx
);
426 isc_mem_put(mctx
, tkey
, sizeof(dns_tsigkey_t
));
432 * Find a few nodes to destroy if possible.
435 cleanup_ring(dns_tsig_keyring_t
*ring
)
438 dns_rbtnodechain_t chain
;
439 dns_name_t foundname
;
440 dns_fixedname_t fixedorigin
;
447 * Start up a new iterator each time.
449 isc_stdtime_get(&now
);
450 dns_name_init(&foundname
, NULL
);
451 dns_fixedname_init(&fixedorigin
);
452 origin
= dns_fixedname_name(&fixedorigin
);
455 dns_rbtnodechain_init(&chain
, ring
->mctx
);
456 result
= dns_rbtnodechain_first(&chain
, ring
->keys
, &foundname
,
458 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_NEWORIGIN
) {
459 dns_rbtnodechain_invalidate(&chain
);
465 dns_rbtnodechain_current(&chain
, &foundname
, origin
, &node
);
469 && isc_refcount_current(&tkey
->refs
) == 1
470 && tkey
->inception
!= tkey
->expire
471 && tkey
->expire
< now
) {
472 tsig_log(tkey
, 2, "tsig expire: deleting");
474 dns_rbtnodechain_invalidate(&chain
);
475 (void)dns_rbt_deletename(ring
->keys
,
481 result
= dns_rbtnodechain_next(&chain
, &foundname
,
483 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_NEWORIGIN
) {
484 dns_rbtnodechain_invalidate(&chain
);
492 dns_tsigkey_create(dns_name_t
*name
, dns_name_t
*algorithm
,
493 unsigned char *secret
, int length
, isc_boolean_t generated
,
494 dns_name_t
*creator
, isc_stdtime_t inception
,
495 isc_stdtime_t expire
, isc_mem_t
*mctx
,
496 dns_tsig_keyring_t
*ring
, dns_tsigkey_t
**key
)
498 dst_key_t
*dstkey
= NULL
;
501 REQUIRE(length
>= 0);
503 REQUIRE(secret
!= NULL
);
505 if (dns_name_equal(algorithm
, DNS_TSIG_HMACMD5_NAME
)) {
506 if (secret
!= NULL
) {
509 isc_buffer_init(&b
, secret
, length
);
510 isc_buffer_add(&b
, length
);
511 result
= dst_key_frombuffer(name
, DST_ALG_HMACMD5
,
516 if (result
!= ISC_R_SUCCESS
)
519 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA1_NAME
)) {
520 if (secret
!= NULL
) {
523 isc_buffer_init(&b
, secret
, length
);
524 isc_buffer_add(&b
, length
);
525 result
= dst_key_frombuffer(name
, DST_ALG_HMACSHA1
,
530 if (result
!= ISC_R_SUCCESS
)
533 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA224_NAME
)) {
534 if (secret
!= NULL
) {
537 isc_buffer_init(&b
, secret
, length
);
538 isc_buffer_add(&b
, length
);
539 result
= dst_key_frombuffer(name
, DST_ALG_HMACSHA224
,
544 if (result
!= ISC_R_SUCCESS
)
547 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA256_NAME
)) {
548 if (secret
!= NULL
) {
551 isc_buffer_init(&b
, secret
, length
);
552 isc_buffer_add(&b
, length
);
553 result
= dst_key_frombuffer(name
, DST_ALG_HMACSHA256
,
558 if (result
!= ISC_R_SUCCESS
)
561 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA384_NAME
)) {
562 if (secret
!= NULL
) {
565 isc_buffer_init(&b
, secret
, length
);
566 isc_buffer_add(&b
, length
);
567 result
= dst_key_frombuffer(name
, DST_ALG_HMACSHA384
,
572 if (result
!= ISC_R_SUCCESS
)
575 } else if (dns_name_equal(algorithm
, DNS_TSIG_HMACSHA512_NAME
)) {
576 if (secret
!= NULL
) {
579 isc_buffer_init(&b
, secret
, length
);
580 isc_buffer_add(&b
, length
);
581 result
= dst_key_frombuffer(name
, DST_ALG_HMACSHA512
,
586 if (result
!= ISC_R_SUCCESS
)
589 } else if (length
> 0)
590 return (DNS_R_BADALG
);
592 result
= dns_tsigkey_createfromkey(name
, algorithm
, dstkey
,
594 inception
, expire
, mctx
, ring
, key
);
595 if (result
!= ISC_R_SUCCESS
&& dstkey
!= NULL
)
596 dst_key_free(&dstkey
);
601 dns_tsigkey_attach(dns_tsigkey_t
*source
, dns_tsigkey_t
**targetp
) {
602 REQUIRE(VALID_TSIG_KEY(source
));
603 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
605 isc_refcount_increment(&source
->refs
, NULL
);
610 tsigkey_free(dns_tsigkey_t
*key
) {
611 REQUIRE(VALID_TSIG_KEY(key
));
614 dns_name_free(&key
->name
, key
->mctx
);
615 if (algname_is_allocated(key
->algorithm
)) {
616 dns_name_free(key
->algorithm
, key
->mctx
);
617 isc_mem_put(key
->mctx
, key
->algorithm
, sizeof(dns_name_t
));
619 if (key
->key
!= NULL
)
620 dst_key_free(&key
->key
);
621 if (key
->creator
!= NULL
) {
622 dns_name_free(key
->creator
, key
->mctx
);
623 isc_mem_put(key
->mctx
, key
->creator
, sizeof(dns_name_t
));
625 isc_refcount_destroy(&key
->refs
);
626 isc_mem_putanddetach(&key
->mctx
, key
, sizeof(dns_tsigkey_t
));
630 dns_tsigkey_detach(dns_tsigkey_t
**keyp
) {
634 REQUIRE(keyp
!= NULL
);
635 REQUIRE(VALID_TSIG_KEY(*keyp
));
638 isc_refcount_decrement(&key
->refs
, &refs
);
647 dns_tsigkey_setdeleted(dns_tsigkey_t
*key
) {
648 REQUIRE(VALID_TSIG_KEY(key
));
649 REQUIRE(key
->ring
!= NULL
);
651 RWLOCK(&key
->ring
->lock
, isc_rwlocktype_write
);
652 (void)dns_rbt_deletename(key
->ring
->keys
, &key
->name
, ISC_FALSE
);
653 RWUNLOCK(&key
->ring
->lock
, isc_rwlocktype_write
);
657 dns_tsig_sign(dns_message_t
*msg
) {
659 dns_rdata_any_tsig_t tsig
, querytsig
;
660 unsigned char data
[128];
661 isc_buffer_t databuf
, sigbuf
;
662 isc_buffer_t
*dynbuf
;
664 dns_rdata_t
*rdata
= NULL
;
665 dns_rdatalist_t
*datalist
;
666 dns_rdataset_t
*dataset
;
670 dst_context_t
*ctx
= NULL
;
672 unsigned char badtimedata
[BADTIMELEN
];
673 unsigned int sigsize
= 0;
675 REQUIRE(msg
!= NULL
);
676 REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg
)));
679 * If this is a response, there should be a query tsig.
681 if (is_response(msg
) && msg
->querytsig
== NULL
)
682 return (DNS_R_EXPECTEDTSIG
);
687 key
= dns_message_gettsigkey(msg
);
690 tsig
.common
.rdclass
= dns_rdataclass_any
;
691 tsig
.common
.rdtype
= dns_rdatatype_tsig
;
692 ISC_LINK_INIT(&tsig
.common
, link
);
693 dns_name_init(&tsig
.algorithm
, NULL
);
694 dns_name_clone(key
->algorithm
, &tsig
.algorithm
);
696 isc_stdtime_get(&now
);
697 tsig
.timesigned
= now
+ msg
->timeadjust
;
698 tsig
.fudge
= DNS_TSIG_FUDGE
;
700 tsig
.originalid
= msg
->id
;
702 isc_buffer_init(&databuf
, data
, sizeof(data
));
704 if (is_response(msg
))
705 tsig
.error
= msg
->querytsigstatus
;
707 tsig
.error
= dns_rcode_noerror
;
709 if (tsig
.error
!= dns_tsigerror_badtime
) {
713 isc_buffer_t otherbuf
;
715 tsig
.otherlen
= BADTIMELEN
;
716 tsig
.other
= badtimedata
;
717 isc_buffer_init(&otherbuf
, tsig
.other
, tsig
.otherlen
);
718 isc_buffer_putuint48(&otherbuf
, tsig
.timesigned
);
721 if (key
->key
!= NULL
&& tsig
.error
!= dns_tsigerror_badsig
) {
722 unsigned char header
[DNS_MESSAGE_HEADERLEN
];
723 isc_buffer_t headerbuf
;
724 isc_uint16_t digestbits
;
726 ret
= dst_context_create(key
->key
, mctx
, &ctx
);
727 if (ret
!= ISC_R_SUCCESS
)
731 * If this is a response, digest the query signature.
733 if (is_response(msg
)) {
734 dns_rdata_t querytsigrdata
= DNS_RDATA_INIT
;
736 ret
= dns_rdataset_first(msg
->querytsig
);
737 if (ret
!= ISC_R_SUCCESS
)
738 goto cleanup_context
;
739 dns_rdataset_current(msg
->querytsig
, &querytsigrdata
);
740 ret
= dns_rdata_tostruct(&querytsigrdata
, &querytsig
,
742 if (ret
!= ISC_R_SUCCESS
)
743 goto cleanup_context
;
744 isc_buffer_putuint16(&databuf
, querytsig
.siglen
);
745 if (isc_buffer_availablelength(&databuf
) <
748 goto cleanup_context
;
750 isc_buffer_putmem(&databuf
, querytsig
.signature
,
752 isc_buffer_usedregion(&databuf
, &r
);
753 ret
= dst_context_adddata(ctx
, &r
);
754 if (ret
!= ISC_R_SUCCESS
)
755 goto cleanup_context
;
761 isc_buffer_init(&headerbuf
, header
, sizeof(header
));
762 dns_message_renderheader(msg
, &headerbuf
);
763 isc_buffer_usedregion(&headerbuf
, &r
);
764 ret
= dst_context_adddata(ctx
, &r
);
765 if (ret
!= ISC_R_SUCCESS
)
766 goto cleanup_context
;
769 * Digest the remainder of the message.
771 isc_buffer_usedregion(msg
->buffer
, &r
);
772 isc_region_consume(&r
, DNS_MESSAGE_HEADERLEN
);
773 ret
= dst_context_adddata(ctx
, &r
);
774 if (ret
!= ISC_R_SUCCESS
)
775 goto cleanup_context
;
777 if (msg
->tcp_continuation
== 0) {
779 * Digest the name, class, ttl, alg.
781 dns_name_toregion(&key
->name
, &r
);
782 ret
= dst_context_adddata(ctx
, &r
);
783 if (ret
!= ISC_R_SUCCESS
)
784 goto cleanup_context
;
786 isc_buffer_clear(&databuf
);
787 isc_buffer_putuint16(&databuf
, dns_rdataclass_any
);
788 isc_buffer_putuint32(&databuf
, 0); /* ttl */
789 isc_buffer_usedregion(&databuf
, &r
);
790 ret
= dst_context_adddata(ctx
, &r
);
791 if (ret
!= ISC_R_SUCCESS
)
792 goto cleanup_context
;
794 dns_name_toregion(&tsig
.algorithm
, &r
);
795 ret
= dst_context_adddata(ctx
, &r
);
796 if (ret
!= ISC_R_SUCCESS
)
797 goto cleanup_context
;
800 /* Digest the timesigned and fudge */
801 isc_buffer_clear(&databuf
);
802 if (tsig
.error
== dns_tsigerror_badtime
)
803 tsig
.timesigned
= querytsig
.timesigned
;
804 isc_buffer_putuint48(&databuf
, tsig
.timesigned
);
805 isc_buffer_putuint16(&databuf
, tsig
.fudge
);
806 isc_buffer_usedregion(&databuf
, &r
);
807 ret
= dst_context_adddata(ctx
, &r
);
808 if (ret
!= ISC_R_SUCCESS
)
809 goto cleanup_context
;
811 if (msg
->tcp_continuation
== 0) {
813 * Digest the error and other data length.
815 isc_buffer_clear(&databuf
);
816 isc_buffer_putuint16(&databuf
, tsig
.error
);
817 isc_buffer_putuint16(&databuf
, tsig
.otherlen
);
819 isc_buffer_usedregion(&databuf
, &r
);
820 ret
= dst_context_adddata(ctx
, &r
);
821 if (ret
!= ISC_R_SUCCESS
)
822 goto cleanup_context
;
825 * Digest the error and other data.
827 if (tsig
.otherlen
> 0) {
828 r
.length
= tsig
.otherlen
;
830 ret
= dst_context_adddata(ctx
, &r
);
831 if (ret
!= ISC_R_SUCCESS
)
832 goto cleanup_context
;
836 ret
= dst_key_sigsize(key
->key
, &sigsize
);
837 if (ret
!= ISC_R_SUCCESS
)
838 goto cleanup_context
;
839 tsig
.signature
= (unsigned char *) isc_mem_get(mctx
, sigsize
);
840 if (tsig
.signature
== NULL
) {
841 ret
= ISC_R_NOMEMORY
;
842 goto cleanup_context
;
845 isc_buffer_init(&sigbuf
, tsig
.signature
, sigsize
);
846 ret
= dst_context_sign(ctx
, &sigbuf
);
847 if (ret
!= ISC_R_SUCCESS
)
848 goto cleanup_signature
;
849 dst_context_destroy(&ctx
);
850 digestbits
= dst_key_getbits(key
->key
);
851 if (digestbits
!= 0) {
852 unsigned int bytes
= (digestbits
+ 1) / 8;
853 if (is_response(msg
) && bytes
< querytsig
.siglen
)
854 bytes
= querytsig
.siglen
;
855 if (bytes
> isc_buffer_usedlength(&sigbuf
))
856 bytes
= isc_buffer_usedlength(&sigbuf
);
859 tsig
.siglen
= isc_buffer_usedlength(&sigbuf
);
862 tsig
.signature
= NULL
;
865 ret
= dns_message_gettemprdata(msg
, &rdata
);
866 if (ret
!= ISC_R_SUCCESS
)
867 goto cleanup_signature
;
868 ret
= isc_buffer_allocate(msg
->mctx
, &dynbuf
, 512);
869 if (ret
!= ISC_R_SUCCESS
)
871 ret
= dns_rdata_fromstruct(rdata
, dns_rdataclass_any
,
872 dns_rdatatype_tsig
, &tsig
, dynbuf
);
873 if (ret
!= ISC_R_SUCCESS
)
876 dns_message_takebuffer(msg
, &dynbuf
);
878 if (tsig
.signature
!= NULL
) {
879 isc_mem_put(mctx
, tsig
.signature
, sigsize
);
880 tsig
.signature
= NULL
;
884 ret
= dns_message_gettempname(msg
, &owner
);
885 if (ret
!= ISC_R_SUCCESS
)
887 dns_name_init(owner
, NULL
);
888 ret
= dns_name_dup(&key
->name
, msg
->mctx
, owner
);
889 if (ret
!= ISC_R_SUCCESS
)
893 ret
= dns_message_gettemprdatalist(msg
, &datalist
);
894 if (ret
!= ISC_R_SUCCESS
)
897 ret
= dns_message_gettemprdataset(msg
, &dataset
);
898 if (ret
!= ISC_R_SUCCESS
)
899 goto cleanup_rdatalist
;
900 datalist
->rdclass
= dns_rdataclass_any
;
901 datalist
->type
= dns_rdatatype_tsig
;
902 datalist
->covers
= 0;
904 ISC_LIST_INIT(datalist
->rdata
);
905 ISC_LIST_APPEND(datalist
->rdata
, rdata
, link
);
906 dns_rdataset_init(dataset
);
907 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist
, dataset
)
910 msg
->tsigname
= owner
;
912 return (ISC_R_SUCCESS
);
915 dns_message_puttemprdatalist(msg
, &datalist
);
917 dns_message_puttempname(msg
, &owner
);
920 isc_buffer_free(&dynbuf
);
922 dns_message_puttemprdata(msg
, &rdata
);
924 if (tsig
.signature
!= NULL
)
925 isc_mem_put(mctx
, tsig
.signature
, sigsize
);
928 dst_context_destroy(&ctx
);
933 dns_tsig_verify(isc_buffer_t
*source
, dns_message_t
*msg
,
934 dns_tsig_keyring_t
*ring1
, dns_tsig_keyring_t
*ring2
)
936 dns_rdata_any_tsig_t tsig
, querytsig
;
937 isc_region_t r
, source_r
, header_r
, sig_r
;
938 isc_buffer_t databuf
;
939 unsigned char data
[32];
941 dns_rdata_t rdata
= DNS_RDATA_INIT
;
944 dns_tsigkey_t
*tsigkey
;
945 dst_key_t
*key
= NULL
;
946 unsigned char header
[DNS_MESSAGE_HEADERLEN
];
947 dst_context_t
*ctx
= NULL
;
949 isc_uint16_t addcount
, id
;
953 REQUIRE(source
!= NULL
);
954 REQUIRE(DNS_MESSAGE_VALID(msg
));
955 tsigkey
= dns_message_gettsigkey(msg
);
957 REQUIRE(tsigkey
== NULL
|| VALID_TSIG_KEY(tsigkey
));
959 msg
->verify_attempted
= 1;
961 if (msg
->tcp_continuation
) {
962 if (tsigkey
== NULL
|| msg
->querytsig
== NULL
)
963 return (DNS_R_UNEXPECTEDTSIG
);
964 return (tsig_verify_tcp(source
, msg
));
968 * There should be a TSIG record...
970 if (msg
->tsig
== NULL
)
971 return (DNS_R_EXPECTEDTSIG
);
974 * If this is a response and there's no key or query TSIG, there
975 * shouldn't be one on the response.
977 if (is_response(msg
) &&
978 (tsigkey
== NULL
|| msg
->querytsig
== NULL
))
979 return (DNS_R_UNEXPECTEDTSIG
);
984 * If we're here, we know the message is well formed and contains a
988 keyname
= msg
->tsigname
;
989 ret
= dns_rdataset_first(msg
->tsig
);
990 if (ret
!= ISC_R_SUCCESS
)
992 dns_rdataset_current(msg
->tsig
, &rdata
);
993 ret
= dns_rdata_tostruct(&rdata
, &tsig
, NULL
);
994 if (ret
!= ISC_R_SUCCESS
)
996 dns_rdata_reset(&rdata
);
997 if (is_response(msg
)) {
998 ret
= dns_rdataset_first(msg
->querytsig
);
999 if (ret
!= ISC_R_SUCCESS
)
1001 dns_rdataset_current(msg
->querytsig
, &rdata
);
1002 ret
= dns_rdata_tostruct(&rdata
, &querytsig
, NULL
);
1003 if (ret
!= ISC_R_SUCCESS
)
1008 * Do the key name and algorithm match that of the query?
1010 if (is_response(msg
) &&
1011 (!dns_name_equal(keyname
, &tsigkey
->name
) ||
1012 !dns_name_equal(&tsig
.algorithm
, &querytsig
.algorithm
))) {
1013 msg
->tsigstatus
= dns_tsigerror_badkey
;
1014 tsig_log(msg
->tsigkey
, 2,
1015 "key name and algorithm do not match");
1016 return (DNS_R_TSIGVERIFYFAILURE
);
1020 * Get the current time.
1022 isc_stdtime_get(&now
);
1025 * Find dns_tsigkey_t based on keyname.
1027 if (tsigkey
== NULL
) {
1028 ret
= ISC_R_NOTFOUND
;
1030 ret
= dns_tsigkey_find(&tsigkey
, keyname
,
1031 &tsig
.algorithm
, ring1
);
1032 if (ret
== ISC_R_NOTFOUND
&& ring2
!= NULL
)
1033 ret
= dns_tsigkey_find(&tsigkey
, keyname
,
1034 &tsig
.algorithm
, ring2
);
1035 if (ret
!= ISC_R_SUCCESS
) {
1036 msg
->tsigstatus
= dns_tsigerror_badkey
;
1037 ret
= dns_tsigkey_create(keyname
, &tsig
.algorithm
,
1038 NULL
, 0, ISC_FALSE
, NULL
,
1040 mctx
, NULL
, &msg
->tsigkey
);
1041 if (ret
!= ISC_R_SUCCESS
)
1043 tsig_log(msg
->tsigkey
, 2, "unknown key");
1044 return (DNS_R_TSIGVERIFYFAILURE
);
1046 msg
->tsigkey
= tsigkey
;
1054 if (now
+ msg
->timeadjust
> tsig
.timesigned
+ tsig
.fudge
) {
1055 msg
->tsigstatus
= dns_tsigerror_badtime
;
1056 tsig_log(msg
->tsigkey
, 2, "signature has expired");
1057 return (DNS_R_CLOCKSKEW
);
1058 } else if (now
+ msg
->timeadjust
< tsig
.timesigned
- tsig
.fudge
) {
1059 msg
->tsigstatus
= dns_tsigerror_badtime
;
1060 tsig_log(msg
->tsigkey
, 2, "signature is in the future");
1061 return (DNS_R_CLOCKSKEW
);
1065 * Check digest length.
1067 alg
= dst_key_alg(key
);
1068 ret
= dst_key_sigsize(key
, &siglen
);
1069 if (ret
!= ISC_R_SUCCESS
)
1071 if (alg
== DST_ALG_HMACMD5
|| alg
== DST_ALG_HMACSHA1
||
1072 alg
== DST_ALG_HMACSHA224
|| alg
== DST_ALG_HMACSHA256
||
1073 alg
== DST_ALG_HMACSHA384
|| alg
== DST_ALG_HMACSHA512
) {
1074 isc_uint16_t digestbits
= dst_key_getbits(key
);
1075 if (tsig
.siglen
> siglen
) {
1076 tsig_log(msg
->tsigkey
, 2, "signature length to big");
1077 return (DNS_R_FORMERR
);
1079 if (tsig
.siglen
> 0 &&
1080 (tsig
.siglen
< 10 || tsig
.siglen
< ((siglen
+ 1) / 2))) {
1081 tsig_log(msg
->tsigkey
, 2,
1082 "signature length below minimum");
1083 return (DNS_R_FORMERR
);
1085 if (tsig
.siglen
> 0 && digestbits
!= 0 &&
1086 tsig
.siglen
< ((digestbits
+ 1) / 8)) {
1087 msg
->tsigstatus
= dns_tsigerror_badtrunc
;
1088 tsig_log(msg
->tsigkey
, 2,
1089 "truncated signature length too small");
1090 return (DNS_R_TSIGVERIFYFAILURE
);
1092 if (tsig
.siglen
> 0 && digestbits
== 0 &&
1093 tsig
.siglen
< siglen
) {
1094 msg
->tsigstatus
= dns_tsigerror_badtrunc
;
1095 tsig_log(msg
->tsigkey
, 2, "signature length too small");
1096 return (DNS_R_TSIGVERIFYFAILURE
);
1100 if (tsig
.siglen
> 0) {
1101 sig_r
.base
= tsig
.signature
;
1102 sig_r
.length
= tsig
.siglen
;
1104 ret
= dst_context_create(key
, mctx
, &ctx
);
1105 if (ret
!= ISC_R_SUCCESS
)
1108 if (is_response(msg
)) {
1109 isc_buffer_init(&databuf
, data
, sizeof(data
));
1110 isc_buffer_putuint16(&databuf
, querytsig
.siglen
);
1111 isc_buffer_usedregion(&databuf
, &r
);
1112 ret
= dst_context_adddata(ctx
, &r
);
1113 if (ret
!= ISC_R_SUCCESS
)
1114 goto cleanup_context
;
1115 if (querytsig
.siglen
> 0) {
1116 r
.length
= querytsig
.siglen
;
1117 r
.base
= querytsig
.signature
;
1118 ret
= dst_context_adddata(ctx
, &r
);
1119 if (ret
!= ISC_R_SUCCESS
)
1120 goto cleanup_context
;
1125 * Extract the header.
1127 isc_buffer_usedregion(source
, &r
);
1128 memcpy(header
, r
.base
, DNS_MESSAGE_HEADERLEN
);
1129 isc_region_consume(&r
, DNS_MESSAGE_HEADERLEN
);
1132 * Decrement the additional field counter.
1134 memcpy(&addcount
, &header
[DNS_MESSAGE_HEADERLEN
- 2], 2);
1135 addcount
= htons((isc_uint16_t
)(ntohs(addcount
) - 1));
1136 memcpy(&header
[DNS_MESSAGE_HEADERLEN
- 2], &addcount
, 2);
1139 * Put in the original id.
1141 id
= htons(tsig
.originalid
);
1142 memcpy(&header
[0], &id
, 2);
1145 * Digest the modified header.
1147 header_r
.base
= (unsigned char *) header
;
1148 header_r
.length
= DNS_MESSAGE_HEADERLEN
;
1149 ret
= dst_context_adddata(ctx
, &header_r
);
1150 if (ret
!= ISC_R_SUCCESS
)
1151 goto cleanup_context
;
1154 * Digest all non-TSIG records.
1156 isc_buffer_usedregion(source
, &source_r
);
1157 r
.base
= source_r
.base
+ DNS_MESSAGE_HEADERLEN
;
1158 r
.length
= msg
->sigstart
- DNS_MESSAGE_HEADERLEN
;
1159 ret
= dst_context_adddata(ctx
, &r
);
1160 if (ret
!= ISC_R_SUCCESS
)
1161 goto cleanup_context
;
1164 * Digest the key name.
1166 dns_name_toregion(&tsigkey
->name
, &r
);
1167 ret
= dst_context_adddata(ctx
, &r
);
1168 if (ret
!= ISC_R_SUCCESS
)
1169 goto cleanup_context
;
1171 isc_buffer_init(&databuf
, data
, sizeof(data
));
1172 isc_buffer_putuint16(&databuf
, tsig
.common
.rdclass
);
1173 isc_buffer_putuint32(&databuf
, msg
->tsig
->ttl
);
1174 isc_buffer_usedregion(&databuf
, &r
);
1175 ret
= dst_context_adddata(ctx
, &r
);
1176 if (ret
!= ISC_R_SUCCESS
)
1177 goto cleanup_context
;
1180 * Digest the key algorithm.
1182 dns_name_toregion(tsigkey
->algorithm
, &r
);
1183 ret
= dst_context_adddata(ctx
, &r
);
1184 if (ret
!= ISC_R_SUCCESS
)
1185 goto cleanup_context
;
1187 isc_buffer_clear(&databuf
);
1188 isc_buffer_putuint48(&databuf
, tsig
.timesigned
);
1189 isc_buffer_putuint16(&databuf
, tsig
.fudge
);
1190 isc_buffer_putuint16(&databuf
, tsig
.error
);
1191 isc_buffer_putuint16(&databuf
, tsig
.otherlen
);
1192 isc_buffer_usedregion(&databuf
, &r
);
1193 ret
= dst_context_adddata(ctx
, &r
);
1194 if (ret
!= ISC_R_SUCCESS
)
1195 goto cleanup_context
;
1197 if (tsig
.otherlen
> 0) {
1198 r
.base
= tsig
.other
;
1199 r
.length
= tsig
.otherlen
;
1200 ret
= dst_context_adddata(ctx
, &r
);
1201 if (ret
!= ISC_R_SUCCESS
)
1202 goto cleanup_context
;
1205 ret
= dst_context_verify(ctx
, &sig_r
);
1206 if (ret
== DST_R_VERIFYFAILURE
) {
1207 msg
->tsigstatus
= dns_tsigerror_badsig
;
1208 ret
= DNS_R_TSIGVERIFYFAILURE
;
1209 tsig_log(msg
->tsigkey
, 2,
1210 "signature failed to verify(1)");
1211 goto cleanup_context
;
1212 } else if (ret
!= ISC_R_SUCCESS
)
1213 goto cleanup_context
;
1215 dst_context_destroy(&ctx
);
1216 } else if (tsig
.error
!= dns_tsigerror_badsig
&&
1217 tsig
.error
!= dns_tsigerror_badkey
) {
1218 msg
->tsigstatus
= dns_tsigerror_badsig
;
1219 tsig_log(msg
->tsigkey
, 2, "signature was empty");
1220 return (DNS_R_TSIGVERIFYFAILURE
);
1223 msg
->tsigstatus
= dns_rcode_noerror
;
1225 if (tsig
.error
!= dns_rcode_noerror
) {
1226 if (tsig
.error
== dns_tsigerror_badtime
)
1227 return (DNS_R_CLOCKSKEW
);
1229 return (DNS_R_TSIGERRORSET
);
1232 msg
->verified_sig
= 1;
1234 return (ISC_R_SUCCESS
);
1238 dst_context_destroy(&ctx
);
1244 tsig_verify_tcp(isc_buffer_t
*source
, dns_message_t
*msg
) {
1245 dns_rdata_any_tsig_t tsig
, querytsig
;
1246 isc_region_t r
, source_r
, header_r
, sig_r
;
1247 isc_buffer_t databuf
;
1248 unsigned char data
[32];
1249 dns_name_t
*keyname
;
1250 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1253 dns_tsigkey_t
*tsigkey
;
1254 dst_key_t
*key
= NULL
;
1255 unsigned char header
[DNS_MESSAGE_HEADERLEN
];
1256 isc_uint16_t addcount
, id
;
1257 isc_boolean_t has_tsig
= ISC_FALSE
;
1260 REQUIRE(source
!= NULL
);
1261 REQUIRE(msg
!= NULL
);
1262 REQUIRE(dns_message_gettsigkey(msg
) != NULL
);
1263 REQUIRE(msg
->tcp_continuation
== 1);
1264 REQUIRE(msg
->querytsig
!= NULL
);
1266 if (!is_response(msg
))
1267 return (DNS_R_EXPECTEDRESPONSE
);
1271 tsigkey
= dns_message_gettsigkey(msg
);
1274 * Extract and parse the previous TSIG
1276 ret
= dns_rdataset_first(msg
->querytsig
);
1277 if (ret
!= ISC_R_SUCCESS
)
1279 dns_rdataset_current(msg
->querytsig
, &rdata
);
1280 ret
= dns_rdata_tostruct(&rdata
, &querytsig
, NULL
);
1281 if (ret
!= ISC_R_SUCCESS
)
1283 dns_rdata_reset(&rdata
);
1286 * If there is a TSIG in this message, do some checks.
1288 if (msg
->tsig
!= NULL
) {
1289 has_tsig
= ISC_TRUE
;
1291 keyname
= msg
->tsigname
;
1292 ret
= dns_rdataset_first(msg
->tsig
);
1293 if (ret
!= ISC_R_SUCCESS
)
1294 goto cleanup_querystruct
;
1295 dns_rdataset_current(msg
->tsig
, &rdata
);
1296 ret
= dns_rdata_tostruct(&rdata
, &tsig
, NULL
);
1297 if (ret
!= ISC_R_SUCCESS
)
1298 goto cleanup_querystruct
;
1301 * Do the key name and algorithm match that of the query?
1303 if (!dns_name_equal(keyname
, &tsigkey
->name
) ||
1304 !dns_name_equal(&tsig
.algorithm
, &querytsig
.algorithm
)) {
1305 msg
->tsigstatus
= dns_tsigerror_badkey
;
1306 ret
= DNS_R_TSIGVERIFYFAILURE
;
1307 tsig_log(msg
->tsigkey
, 2,
1308 "key name and algorithm do not match");
1309 goto cleanup_querystruct
;
1315 isc_stdtime_get(&now
);
1317 if (now
+ msg
->timeadjust
> tsig
.timesigned
+ tsig
.fudge
) {
1318 msg
->tsigstatus
= dns_tsigerror_badtime
;
1319 tsig_log(msg
->tsigkey
, 2, "signature has expired");
1320 ret
= DNS_R_CLOCKSKEW
;
1321 goto cleanup_querystruct
;
1322 } else if (now
+ msg
->timeadjust
<
1323 tsig
.timesigned
- tsig
.fudge
) {
1324 msg
->tsigstatus
= dns_tsigerror_badtime
;
1325 tsig_log(msg
->tsigkey
, 2,
1326 "signature is in the future");
1327 ret
= DNS_R_CLOCKSKEW
;
1328 goto cleanup_querystruct
;
1334 if (msg
->tsigctx
== NULL
) {
1335 ret
= dst_context_create(key
, mctx
, &msg
->tsigctx
);
1336 if (ret
!= ISC_R_SUCCESS
)
1337 goto cleanup_querystruct
;
1340 * Digest the length of the query signature
1342 isc_buffer_init(&databuf
, data
, sizeof(data
));
1343 isc_buffer_putuint16(&databuf
, querytsig
.siglen
);
1344 isc_buffer_usedregion(&databuf
, &r
);
1345 ret
= dst_context_adddata(msg
->tsigctx
, &r
);
1346 if (ret
!= ISC_R_SUCCESS
)
1347 goto cleanup_context
;
1350 * Digest the data of the query signature
1352 if (querytsig
.siglen
> 0) {
1353 r
.length
= querytsig
.siglen
;
1354 r
.base
= querytsig
.signature
;
1355 ret
= dst_context_adddata(msg
->tsigctx
, &r
);
1356 if (ret
!= ISC_R_SUCCESS
)
1357 goto cleanup_context
;
1362 * Extract the header.
1364 isc_buffer_usedregion(source
, &r
);
1365 memcpy(header
, r
.base
, DNS_MESSAGE_HEADERLEN
);
1366 isc_region_consume(&r
, DNS_MESSAGE_HEADERLEN
);
1369 * Decrement the additional field counter if necessary.
1372 memcpy(&addcount
, &header
[DNS_MESSAGE_HEADERLEN
- 2], 2);
1373 addcount
= htons((isc_uint16_t
)(ntohs(addcount
) - 1));
1374 memcpy(&header
[DNS_MESSAGE_HEADERLEN
- 2], &addcount
, 2);
1378 * Put in the original id.
1380 /* XXX Can TCP transfers be forwarded? How would that work? */
1382 id
= htons(tsig
.originalid
);
1383 memcpy(&header
[0], &id
, 2);
1387 * Digest the modified header.
1389 header_r
.base
= (unsigned char *) header
;
1390 header_r
.length
= DNS_MESSAGE_HEADERLEN
;
1391 ret
= dst_context_adddata(msg
->tsigctx
, &header_r
);
1392 if (ret
!= ISC_R_SUCCESS
)
1393 goto cleanup_context
;
1396 * Digest all non-TSIG records.
1398 isc_buffer_usedregion(source
, &source_r
);
1399 r
.base
= source_r
.base
+ DNS_MESSAGE_HEADERLEN
;
1401 r
.length
= msg
->sigstart
- DNS_MESSAGE_HEADERLEN
;
1403 r
.length
= source_r
.length
- DNS_MESSAGE_HEADERLEN
;
1404 ret
= dst_context_adddata(msg
->tsigctx
, &r
);
1405 if (ret
!= ISC_R_SUCCESS
)
1406 goto cleanup_context
;
1409 * Digest the time signed and fudge.
1412 isc_buffer_init(&databuf
, data
, sizeof(data
));
1413 isc_buffer_putuint48(&databuf
, tsig
.timesigned
);
1414 isc_buffer_putuint16(&databuf
, tsig
.fudge
);
1415 isc_buffer_usedregion(&databuf
, &r
);
1416 ret
= dst_context_adddata(msg
->tsigctx
, &r
);
1417 if (ret
!= ISC_R_SUCCESS
)
1418 goto cleanup_context
;
1420 sig_r
.base
= tsig
.signature
;
1421 sig_r
.length
= tsig
.siglen
;
1422 if (tsig
.siglen
== 0) {
1423 if (tsig
.error
!= dns_rcode_noerror
) {
1424 if (tsig
.error
== dns_tsigerror_badtime
)
1425 ret
= DNS_R_CLOCKSKEW
;
1427 ret
= DNS_R_TSIGERRORSET
;
1429 tsig_log(msg
->tsigkey
, 2,
1430 "signature is empty");
1431 ret
= DNS_R_TSIGVERIFYFAILURE
;
1433 goto cleanup_context
;
1436 ret
= dst_context_verify(msg
->tsigctx
, &sig_r
);
1437 if (ret
== DST_R_VERIFYFAILURE
) {
1438 msg
->tsigstatus
= dns_tsigerror_badsig
;
1439 tsig_log(msg
->tsigkey
, 2,
1440 "signature failed to verify(2)");
1441 ret
= DNS_R_TSIGVERIFYFAILURE
;
1442 goto cleanup_context
;
1444 else if (ret
!= ISC_R_SUCCESS
)
1445 goto cleanup_context
;
1447 dst_context_destroy(&msg
->tsigctx
);
1450 msg
->tsigstatus
= dns_rcode_noerror
;
1451 return (ISC_R_SUCCESS
);
1454 dst_context_destroy(&msg
->tsigctx
);
1456 cleanup_querystruct
:
1457 dns_rdata_freestruct(&querytsig
);
1464 dns_tsigkey_find(dns_tsigkey_t
**tsigkey
, dns_name_t
*name
,
1465 dns_name_t
*algorithm
, dns_tsig_keyring_t
*ring
)
1469 isc_result_t result
;
1471 REQUIRE(tsigkey
!= NULL
);
1472 REQUIRE(*tsigkey
== NULL
);
1473 REQUIRE(name
!= NULL
);
1474 REQUIRE(ring
!= NULL
);
1476 RWLOCK(&ring
->lock
, isc_rwlocktype_write
);
1478 RWUNLOCK(&ring
->lock
, isc_rwlocktype_write
);
1480 isc_stdtime_get(&now
);
1481 RWLOCK(&ring
->lock
, isc_rwlocktype_read
);
1483 result
= dns_rbt_findname(ring
->keys
, name
, 0, NULL
, (void *)&key
);
1484 if (result
== DNS_R_PARTIALMATCH
|| result
== ISC_R_NOTFOUND
) {
1485 RWUNLOCK(&ring
->lock
, isc_rwlocktype_read
);
1486 return (ISC_R_NOTFOUND
);
1488 if (algorithm
!= NULL
&& !dns_name_equal(key
->algorithm
, algorithm
)) {
1489 RWUNLOCK(&ring
->lock
, isc_rwlocktype_read
);
1490 return (ISC_R_NOTFOUND
);
1492 if (key
->inception
!= key
->expire
&& key
->expire
< now
) {
1494 * The key has expired.
1496 RWUNLOCK(&ring
->lock
, isc_rwlocktype_read
);
1497 RWLOCK(&ring
->lock
, isc_rwlocktype_write
);
1498 (void)dns_rbt_deletename(ring
->keys
, name
, ISC_FALSE
);
1499 RWUNLOCK(&ring
->lock
, isc_rwlocktype_write
);
1500 return (ISC_R_NOTFOUND
);
1503 isc_refcount_increment(&key
->refs
, NULL
);
1504 RWUNLOCK(&ring
->lock
, isc_rwlocktype_read
);
1506 return (ISC_R_SUCCESS
);
1510 free_tsignode(void *node
, void *_unused
) {
1515 REQUIRE(node
!= NULL
);
1518 dns_tsigkey_detach(&key
);
1522 dns_tsigkeyring_create(isc_mem_t
*mctx
, dns_tsig_keyring_t
**ringp
) {
1523 isc_result_t result
;
1524 dns_tsig_keyring_t
*ring
;
1526 REQUIRE(mctx
!= NULL
);
1527 REQUIRE(ringp
!= NULL
);
1528 REQUIRE(*ringp
== NULL
);
1530 ring
= isc_mem_get(mctx
, sizeof(dns_tsig_keyring_t
));
1532 return (ISC_R_NOMEMORY
);
1534 result
= isc_rwlock_init(&ring
->lock
, 0, 0);
1535 if (result
!= ISC_R_SUCCESS
) {
1536 isc_mem_put(mctx
, ring
, sizeof(dns_tsig_keyring_t
));
1541 result
= dns_rbt_create(mctx
, free_tsignode
, NULL
, &ring
->keys
);
1542 if (result
!= ISC_R_SUCCESS
) {
1543 isc_rwlock_destroy(&ring
->lock
);
1544 isc_mem_put(mctx
, ring
, sizeof(dns_tsig_keyring_t
));
1548 ring
->writecount
= 0;
1550 isc_mem_attach(mctx
, &ring
->mctx
);
1553 return (ISC_R_SUCCESS
);
1557 dns_tsigkeyring_add(dns_tsig_keyring_t
*ring
, dns_name_t
*name
,
1558 dns_tsigkey_t
*tkey
)
1560 isc_result_t result
;
1562 result
= keyring_add(ring
, name
, tkey
);
1563 if (result
== ISC_R_SUCCESS
)
1564 isc_refcount_increment(&tkey
->refs
, NULL
);
1570 dns_tsigkeyring_destroy(dns_tsig_keyring_t
**ringp
) {
1571 dns_tsig_keyring_t
*ring
;
1573 REQUIRE(ringp
!= NULL
);
1574 REQUIRE(*ringp
!= NULL
);
1579 dns_rbt_destroy(&ring
->keys
);
1580 isc_rwlock_destroy(&ring
->lock
);
1581 isc_mem_putanddetach(&ring
->mctx
, ring
, sizeof(dns_tsig_keyring_t
));