4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2001, 2003 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: tkey.c,v 1.92 2009/09/02 23:48:02 tbox Exp
26 #include <isc/buffer.h>
27 #include <isc/entropy.h>
30 #include <isc/string.h>
33 #include <dns/dnssec.h>
34 #include <dns/fixedname.h>
35 #include <dns/keyvalues.h>
37 #include <dns/message.h>
39 #include <dns/rdata.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
42 #include <dns/rdatastruct.h>
43 #include <dns/result.h>
48 #include <dst/gssapi.h>
50 #define TKEY_RANDOM_AMOUNT 16
52 #define RETERR(x) do { \
54 if (result != ISC_R_SUCCESS) \
59 tkey_log(const char *fmt
, ...) ISC_FORMAT_PRINTF(1, 2);
62 tkey_log(const char *fmt
, ...) {
66 isc_log_vwrite(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
67 DNS_LOGMODULE_REQUEST
, ISC_LOG_DEBUG(4), fmt
, ap
);
72 _dns_tkey_dumpmessage(dns_message_t
*msg
) {
74 unsigned char output
[4096];
77 isc_buffer_init(&outbuf
, output
, sizeof(output
));
78 result
= dns_message_totext(msg
, &dns_master_style_debug
, 0,
80 /* XXXMLG ignore result */
81 fprintf(stderr
, "%.*s\n", (int)isc_buffer_usedlength(&outbuf
),
82 (char *)isc_buffer_base(&outbuf
));
86 dns_tkeyctx_create(isc_mem_t
*mctx
, isc_entropy_t
*ectx
, dns_tkeyctx_t
**tctxp
)
90 REQUIRE(mctx
!= NULL
);
91 REQUIRE(ectx
!= NULL
);
92 REQUIRE(tctxp
!= NULL
&& *tctxp
== NULL
);
94 tctx
= isc_mem_get(mctx
, sizeof(dns_tkeyctx_t
));
96 return (ISC_R_NOMEMORY
);
98 isc_mem_attach(mctx
, &tctx
->mctx
);
100 isc_entropy_attach(ectx
, &tctx
->ectx
);
103 tctx
->gsscred
= NULL
;
106 return (ISC_R_SUCCESS
);
110 dns_tkeyctx_destroy(dns_tkeyctx_t
**tctxp
) {
114 REQUIRE(tctxp
!= NULL
&& *tctxp
!= NULL
);
119 if (tctx
->dhkey
!= NULL
)
120 dst_key_free(&tctx
->dhkey
);
121 if (tctx
->domain
!= NULL
) {
122 if (dns_name_dynamic(tctx
->domain
))
123 dns_name_free(tctx
->domain
, mctx
);
124 isc_mem_put(mctx
, tctx
->domain
, sizeof(dns_name_t
));
126 if (tctx
->gsscred
!= NULL
)
127 dst_gssapi_releasecred(&tctx
->gsscred
);
128 isc_entropy_detach(&tctx
->ectx
);
129 isc_mem_put(mctx
, tctx
, sizeof(dns_tkeyctx_t
));
130 isc_mem_detach(&mctx
);
135 add_rdata_to_list(dns_message_t
*msg
, dns_name_t
*name
, dns_rdata_t
*rdata
,
136 isc_uint32_t ttl
, dns_namelist_t
*namelist
)
139 isc_region_t r
, newr
;
140 dns_rdata_t
*newrdata
= NULL
;
141 dns_name_t
*newname
= NULL
;
142 dns_rdatalist_t
*newlist
= NULL
;
143 dns_rdataset_t
*newset
= NULL
;
144 isc_buffer_t
*tmprdatabuf
= NULL
;
146 RETERR(dns_message_gettemprdata(msg
, &newrdata
));
148 dns_rdata_toregion(rdata
, &r
);
149 RETERR(isc_buffer_allocate(msg
->mctx
, &tmprdatabuf
, r
.length
));
150 isc_buffer_availableregion(tmprdatabuf
, &newr
);
151 memcpy(newr
.base
, r
.base
, r
.length
);
152 dns_rdata_fromregion(newrdata
, rdata
->rdclass
, rdata
->type
, &newr
);
153 dns_message_takebuffer(msg
, &tmprdatabuf
);
155 RETERR(dns_message_gettempname(msg
, &newname
));
156 dns_name_init(newname
, NULL
);
157 RETERR(dns_name_dup(name
, msg
->mctx
, newname
));
159 RETERR(dns_message_gettemprdatalist(msg
, &newlist
));
160 newlist
->rdclass
= newrdata
->rdclass
;
161 newlist
->type
= newrdata
->type
;
164 ISC_LIST_INIT(newlist
->rdata
);
165 ISC_LIST_APPEND(newlist
->rdata
, newrdata
, link
);
167 RETERR(dns_message_gettemprdataset(msg
, &newset
));
168 dns_rdataset_init(newset
);
169 RETERR(dns_rdatalist_tordataset(newlist
, newset
));
171 ISC_LIST_INIT(newname
->list
);
172 ISC_LIST_APPEND(newname
->list
, newset
, link
);
174 ISC_LIST_APPEND(*namelist
, newname
, link
);
176 return (ISC_R_SUCCESS
);
179 if (newrdata
!= NULL
) {
180 if (ISC_LINK_LINKED(newrdata
, link
))
181 ISC_LIST_UNLINK(newlist
->rdata
, newrdata
, link
);
182 dns_message_puttemprdata(msg
, &newrdata
);
185 dns_message_puttempname(msg
, &newname
);
186 if (newset
!= NULL
) {
187 dns_rdataset_disassociate(newset
);
188 dns_message_puttemprdataset(msg
, &newset
);
191 dns_message_puttemprdatalist(msg
, &newlist
);
196 free_namelist(dns_message_t
*msg
, dns_namelist_t
*namelist
) {
200 while (!ISC_LIST_EMPTY(*namelist
)) {
201 name
= ISC_LIST_HEAD(*namelist
);
202 ISC_LIST_UNLINK(*namelist
, name
, link
);
203 while (!ISC_LIST_EMPTY(name
->list
)) {
204 set
= ISC_LIST_HEAD(name
->list
);
205 ISC_LIST_UNLINK(name
->list
, set
, link
);
206 dns_message_puttemprdataset(msg
, &set
);
208 dns_message_puttempname(msg
, &name
);
213 compute_secret(isc_buffer_t
*shared
, isc_region_t
*queryrandomness
,
214 isc_region_t
*serverrandomness
, isc_buffer_t
*secret
)
218 unsigned char digests
[32];
221 isc_buffer_usedregion(shared
, &r
);
224 * MD5 ( query data | DH value ).
226 isc_md5_init(&md5ctx
);
227 isc_md5_update(&md5ctx
, queryrandomness
->base
,
228 queryrandomness
->length
);
229 isc_md5_update(&md5ctx
, r
.base
, r
.length
);
230 isc_md5_final(&md5ctx
, digests
);
233 * MD5 ( server data | DH value ).
235 isc_md5_init(&md5ctx
);
236 isc_md5_update(&md5ctx
, serverrandomness
->base
,
237 serverrandomness
->length
);
238 isc_md5_update(&md5ctx
, r
.base
, r
.length
);
239 isc_md5_final(&md5ctx
, &digests
[ISC_MD5_DIGESTLENGTH
]);
242 * XOR ( DH value, MD5-1 | MD5-2).
244 isc_buffer_availableregion(secret
, &r
);
245 isc_buffer_usedregion(shared
, &r2
);
246 if (r
.length
< sizeof(digests
) || r
.length
< r2
.length
)
247 return (ISC_R_NOSPACE
);
248 if (r2
.length
> sizeof(digests
)) {
249 memcpy(r
.base
, r2
.base
, r2
.length
);
250 for (i
= 0; i
< sizeof(digests
); i
++)
251 r
.base
[i
] ^= digests
[i
];
252 isc_buffer_add(secret
, r2
.length
);
254 memcpy(r
.base
, digests
, sizeof(digests
));
255 for (i
= 0; i
< r2
.length
; i
++)
256 r
.base
[i
] ^= r2
.base
[i
];
257 isc_buffer_add(secret
, sizeof(digests
));
259 return (ISC_R_SUCCESS
);
264 process_dhtkey(dns_message_t
*msg
, dns_name_t
*signer
, dns_name_t
*name
,
265 dns_rdata_tkey_t
*tkeyin
, dns_tkeyctx_t
*tctx
,
266 dns_rdata_tkey_t
*tkeyout
,
267 dns_tsig_keyring_t
*ring
, dns_namelist_t
*namelist
)
269 isc_result_t result
= ISC_R_SUCCESS
;
270 dns_name_t
*keyname
, ourname
;
271 dns_rdataset_t
*keyset
= NULL
;
272 dns_rdata_t keyrdata
= DNS_RDATA_INIT
, ourkeyrdata
= DNS_RDATA_INIT
;
273 isc_boolean_t found_key
= ISC_FALSE
, found_incompatible
= ISC_FALSE
;
274 dst_key_t
*pubkey
= NULL
;
275 isc_buffer_t ourkeybuf
, *shared
= NULL
;
276 isc_region_t r
, r2
, ourkeyr
;
277 unsigned char keydata
[DST_KEY_MAXSIZE
];
278 unsigned int sharedsize
;
280 unsigned char *randomdata
= NULL
, secretdata
[256];
283 if (tctx
->dhkey
== NULL
) {
284 tkey_log("process_dhtkey: tkey-dhkey not defined");
285 tkeyout
->error
= dns_tsigerror_badalg
;
286 return (DNS_R_REFUSED
);
289 if (!dns_name_equal(&tkeyin
->algorithm
, DNS_TSIG_HMACMD5_NAME
)) {
290 tkey_log("process_dhtkey: algorithms other than "
291 "hmac-md5 are not supported");
292 tkeyout
->error
= dns_tsigerror_badalg
;
293 return (ISC_R_SUCCESS
);
297 * Look for a DH KEY record that will work with ours.
299 for (result
= dns_message_firstname(msg
, DNS_SECTION_ADDITIONAL
);
300 result
== ISC_R_SUCCESS
&& !found_key
;
301 result
= dns_message_nextname(msg
, DNS_SECTION_ADDITIONAL
)) {
303 dns_message_currentname(msg
, DNS_SECTION_ADDITIONAL
, &keyname
);
305 result
= dns_message_findtype(keyname
, dns_rdatatype_key
, 0,
307 if (result
!= ISC_R_SUCCESS
)
310 for (result
= dns_rdataset_first(keyset
);
311 result
== ISC_R_SUCCESS
&& !found_key
;
312 result
= dns_rdataset_next(keyset
)) {
313 dns_rdataset_current(keyset
, &keyrdata
);
315 result
= dns_dnssec_keyfromrdata(keyname
, &keyrdata
,
317 if (result
!= ISC_R_SUCCESS
) {
318 dns_rdata_reset(&keyrdata
);
321 if (dst_key_alg(pubkey
) == DNS_KEYALG_DH
) {
322 if (dst_key_paramcompare(pubkey
, tctx
->dhkey
))
324 found_key
= ISC_TRUE
;
328 found_incompatible
= ISC_TRUE
;
330 dst_key_free(&pubkey
);
331 dns_rdata_reset(&keyrdata
);
336 if (found_incompatible
) {
337 tkey_log("process_dhtkey: found an incompatible key");
338 tkeyout
->error
= dns_tsigerror_badkey
;
339 return (ISC_R_SUCCESS
);
341 tkey_log("process_dhtkey: failed to find a key");
342 return (DNS_R_FORMERR
);
346 RETERR(add_rdata_to_list(msg
, keyname
, &keyrdata
, ttl
, namelist
));
348 isc_buffer_init(&ourkeybuf
, keydata
, sizeof(keydata
));
349 RETERR(dst_key_todns(tctx
->dhkey
, &ourkeybuf
));
350 isc_buffer_usedregion(&ourkeybuf
, &ourkeyr
);
351 dns_rdata_fromregion(&ourkeyrdata
, dns_rdataclass_any
,
352 dns_rdatatype_key
, &ourkeyr
);
354 dns_name_init(&ourname
, NULL
);
355 dns_name_clone(dst_key_name(tctx
->dhkey
), &ourname
);
358 * XXXBEW The TTL should be obtained from the database, if it exists.
360 RETERR(add_rdata_to_list(msg
, &ourname
, &ourkeyrdata
, 0, namelist
));
362 RETERR(dst_key_secretsize(tctx
->dhkey
, &sharedsize
));
363 RETERR(isc_buffer_allocate(msg
->mctx
, &shared
, sharedsize
));
365 result
= dst_key_computesecret(pubkey
, tctx
->dhkey
, shared
);
366 if (result
!= ISC_R_SUCCESS
) {
367 tkey_log("process_dhtkey: failed to compute shared secret: %s",
368 isc_result_totext(result
));
371 dst_key_free(&pubkey
);
373 isc_buffer_init(&secret
, secretdata
, sizeof(secretdata
));
375 randomdata
= isc_mem_get(tkeyout
->mctx
, TKEY_RANDOM_AMOUNT
);
376 if (randomdata
== NULL
)
379 result
= isc_entropy_getdata(tctx
->ectx
, randomdata
,
380 TKEY_RANDOM_AMOUNT
, NULL
, 0);
381 if (result
!= ISC_R_SUCCESS
) {
382 tkey_log("process_dhtkey: failed to obtain entropy: %s",
383 isc_result_totext(result
));
388 r
.length
= TKEY_RANDOM_AMOUNT
;
389 r2
.base
= tkeyin
->key
;
390 r2
.length
= tkeyin
->keylen
;
391 RETERR(compute_secret(shared
, &r2
, &r
, &secret
));
392 isc_buffer_free(&shared
);
394 RETERR(dns_tsigkey_create(name
, &tkeyin
->algorithm
,
395 isc_buffer_base(&secret
),
396 isc_buffer_usedlength(&secret
),
397 ISC_TRUE
, signer
, tkeyin
->inception
,
398 tkeyin
->expire
, ring
->mctx
, ring
, NULL
));
400 /* This key is good for a long time */
401 tkeyout
->inception
= tkeyin
->inception
;
402 tkeyout
->expire
= tkeyin
->expire
;
404 tkeyout
->key
= randomdata
;
405 tkeyout
->keylen
= TKEY_RANDOM_AMOUNT
;
407 return (ISC_R_SUCCESS
);
410 if (!ISC_LIST_EMPTY(*namelist
))
411 free_namelist(msg
, namelist
);
413 isc_buffer_free(&shared
);
415 dst_key_free(&pubkey
);
416 if (randomdata
!= NULL
)
417 isc_mem_put(tkeyout
->mctx
, randomdata
, TKEY_RANDOM_AMOUNT
);
422 process_gsstkey(dns_message_t
*msg
, dns_name_t
*signer
, dns_name_t
*name
,
423 dns_rdata_tkey_t
*tkeyin
, dns_tkeyctx_t
*tctx
,
424 dns_rdata_tkey_t
*tkeyout
,
425 dns_tsig_keyring_t
*ring
, dns_namelist_t
*namelist
)
427 isc_result_t result
= ISC_R_SUCCESS
;
428 dst_key_t
*dstkey
= NULL
;
429 dns_tsigkey_t
*tsigkey
= NULL
;
430 dns_fixedname_t principal
;
432 isc_region_t intoken
;
433 isc_buffer_t
*outtoken
= NULL
;
434 gss_ctx_id_t gss_ctx
= NULL
;
439 if (tctx
->gsscred
== NULL
)
440 return (ISC_R_NOPERM
);
442 if (!dns_name_equal(&tkeyin
->algorithm
, DNS_TSIG_GSSAPI_NAME
) &&
443 !dns_name_equal(&tkeyin
->algorithm
, DNS_TSIG_GSSAPIMS_NAME
)) {
444 tkeyout
->error
= dns_tsigerror_badalg
;
445 tkey_log("process_gsstkey(): dns_tsigerror_badalg"); /* XXXSRA */
446 return (ISC_R_SUCCESS
);
450 * XXXDCL need to check for key expiry per 4.1.1
451 * XXXDCL need a way to check fully established, perhaps w/key_flags
454 intoken
.base
= tkeyin
->key
;
455 intoken
.length
= tkeyin
->keylen
;
457 result
= dns_tsigkey_find(&tsigkey
, name
, &tkeyin
->algorithm
, ring
);
458 if (result
== ISC_R_SUCCESS
)
459 gss_ctx
= dst_key_getgssctx(tsigkey
->key
);
462 dns_fixedname_init(&principal
);
464 result
= dst_gssapi_acceptctx(tctx
->gsscred
, &intoken
,
466 dns_fixedname_name(&principal
),
470 dns_tsigkey_detach(&tsigkey
);
472 if (result
== DNS_R_INVALIDTKEY
) {
473 tkeyout
->error
= dns_tsigerror_badkey
;
474 tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */
475 return (ISC_R_SUCCESS
);
476 } else if (result
== ISC_R_FAILURE
)
478 ENSURE(result
== DNS_R_CONTINUE
|| result
== ISC_R_SUCCESS
);
480 * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
483 if (tsigkey
== NULL
) {
484 RETERR(dst_key_fromgssapi(name
, gss_ctx
, msg
->mctx
, &dstkey
));
485 RETERR(dns_tsigkey_createfromkey(name
, &tkeyin
->algorithm
,
487 dns_fixedname_name(&principal
),
490 ring
->mctx
, ring
, NULL
));
493 isc_stdtime_get(&now
);
494 tkeyout
->inception
= tkeyin
->inception
;
495 tkeyout
->expire
= tkeyin
->expire
;
498 tkeyout
->key
= isc_mem_get(tkeyout
->mctx
,
499 isc_buffer_usedlength(outtoken
));
500 if (tkeyout
->key
== NULL
) {
501 result
= ISC_R_NOMEMORY
;
504 tkeyout
->keylen
= isc_buffer_usedlength(outtoken
);
505 memcpy(tkeyout
->key
, isc_buffer_base(outtoken
),
506 isc_buffer_usedlength(outtoken
));
507 isc_buffer_free(&outtoken
);
509 tkeyout
->key
= isc_mem_get(tkeyout
->mctx
, tkeyin
->keylen
);
510 if (tkeyout
->key
== NULL
) {
511 result
= ISC_R_NOMEMORY
;
514 tkeyout
->keylen
= tkeyin
->keylen
;
515 memcpy(tkeyout
->key
, tkeyin
->key
, tkeyin
->keylen
);
518 tkeyout
->error
= dns_rcode_noerror
;
520 tkey_log("process_gsstkey(): dns_tsigerror_noerror"); /* XXXSRA */
522 return (ISC_R_SUCCESS
);
526 dst_key_free(&dstkey
);
528 if (outtoken
!= NULL
)
529 isc_buffer_free(&outtoken
);
531 tkey_log("process_gsstkey(): %s",
532 isc_result_totext(result
)); /* XXXSRA */
538 process_deletetkey(dns_message_t
*msg
, dns_name_t
*signer
, dns_name_t
*name
,
539 dns_rdata_tkey_t
*tkeyin
,
540 dns_rdata_tkey_t
*tkeyout
,
541 dns_tsig_keyring_t
*ring
,
542 dns_namelist_t
*namelist
)
545 dns_tsigkey_t
*tsigkey
= NULL
;
546 dns_name_t
*identity
;
551 result
= dns_tsigkey_find(&tsigkey
, name
, &tkeyin
->algorithm
, ring
);
552 if (result
!= ISC_R_SUCCESS
) {
553 tkeyout
->error
= dns_tsigerror_badname
;
554 return (ISC_R_SUCCESS
);
558 * Only allow a delete if the identity that created the key is the
559 * same as the identity that signed the message.
561 identity
= dns_tsigkey_identity(tsigkey
);
562 if (identity
== NULL
|| !dns_name_equal(identity
, signer
)) {
563 dns_tsigkey_detach(&tsigkey
);
564 return (DNS_R_REFUSED
);
568 * Set the key to be deleted when no references are left. If the key
569 * was not generated with TKEY and is in the config file, it may be
572 dns_tsigkey_setdeleted(tsigkey
);
574 /* Release the reference */
575 dns_tsigkey_detach(&tsigkey
);
577 return (ISC_R_SUCCESS
);
581 dns_tkey_processquery(dns_message_t
*msg
, dns_tkeyctx_t
*tctx
,
582 dns_tsig_keyring_t
*ring
)
584 isc_result_t result
= ISC_R_SUCCESS
;
585 dns_rdata_tkey_t tkeyin
, tkeyout
;
586 isc_boolean_t freetkeyin
= ISC_FALSE
;
587 dns_name_t
*qname
, *name
, *keyname
, *signer
, tsigner
;
588 dns_fixedname_t fkeyname
;
589 dns_rdataset_t
*tkeyset
;
591 dns_namelist_t namelist
;
592 char tkeyoutdata
[512];
593 isc_buffer_t tkeyoutbuf
;
595 REQUIRE(msg
!= NULL
);
596 REQUIRE(tctx
!= NULL
);
597 REQUIRE(ring
!= NULL
);
599 ISC_LIST_INIT(namelist
);
602 * Interpret the question section.
604 result
= dns_message_firstname(msg
, DNS_SECTION_QUESTION
);
605 if (result
!= ISC_R_SUCCESS
)
606 return (DNS_R_FORMERR
);
609 dns_message_currentname(msg
, DNS_SECTION_QUESTION
, &qname
);
612 * Look for a TKEY record that matches the question.
616 result
= dns_message_findname(msg
, DNS_SECTION_ADDITIONAL
, qname
,
617 dns_rdatatype_tkey
, 0, &name
, &tkeyset
);
618 if (result
!= ISC_R_SUCCESS
) {
620 * Try the answer section, since that's where Win2000
623 if (dns_message_findname(msg
, DNS_SECTION_ANSWER
, qname
,
624 dns_rdatatype_tkey
, 0, &name
,
625 &tkeyset
) != ISC_R_SUCCESS
) {
626 result
= DNS_R_FORMERR
;
627 tkey_log("dns_tkey_processquery: couldn't find a TKEY "
628 "matching the question");
632 result
= dns_rdataset_first(tkeyset
);
633 if (result
!= ISC_R_SUCCESS
) {
634 result
= DNS_R_FORMERR
;
637 dns_rdata_init(&rdata
);
638 dns_rdataset_current(tkeyset
, &rdata
);
640 RETERR(dns_rdata_tostruct(&rdata
, &tkeyin
, NULL
));
641 freetkeyin
= ISC_TRUE
;
643 if (tkeyin
.error
!= dns_rcode_noerror
) {
644 result
= DNS_R_FORMERR
;
649 * Before we go any farther, verify that the message was signed.
650 * GSSAPI TKEY doesn't require a signature, the rest do.
652 dns_name_init(&tsigner
, NULL
);
653 result
= dns_message_signer(msg
, &tsigner
);
654 if (result
!= ISC_R_SUCCESS
) {
655 if (tkeyin
.mode
== DNS_TKEYMODE_GSSAPI
&&
656 result
== ISC_R_NOTFOUND
)
659 tkey_log("dns_tkey_processquery: query was not "
660 "properly signed - rejecting");
661 result
= DNS_R_FORMERR
;
667 tkeyout
.common
.rdclass
= tkeyin
.common
.rdclass
;
668 tkeyout
.common
.rdtype
= tkeyin
.common
.rdtype
;
669 ISC_LINK_INIT(&tkeyout
.common
, link
);
670 tkeyout
.mctx
= msg
->mctx
;
672 dns_name_init(&tkeyout
.algorithm
, NULL
);
673 dns_name_clone(&tkeyin
.algorithm
, &tkeyout
.algorithm
);
675 tkeyout
.inception
= tkeyout
.expire
= 0;
676 tkeyout
.mode
= tkeyin
.mode
;
678 tkeyout
.keylen
= tkeyout
.otherlen
= 0;
679 tkeyout
.key
= tkeyout
.other
= NULL
;
682 * A delete operation must have a fully specified key name. If this
683 * is not a delete, we do the following:
685 * keyname = qname + defaultdomain
687 * keyname = <random hex> + defaultdomain
689 if (tkeyin
.mode
!= DNS_TKEYMODE_DELETE
) {
690 dns_tsigkey_t
*tsigkey
= NULL
;
692 if (tctx
->domain
== NULL
&& tkeyin
.mode
!= DNS_TKEYMODE_GSSAPI
) {
693 tkey_log("dns_tkey_processquery: tkey-domain not set");
694 result
= DNS_R_REFUSED
;
698 dns_fixedname_init(&fkeyname
);
699 keyname
= dns_fixedname_name(&fkeyname
);
701 if (!dns_name_equal(qname
, dns_rootname
)) {
702 unsigned int n
= dns_name_countlabels(qname
);
703 RUNTIME_CHECK(dns_name_copy(qname
, keyname
, NULL
)
705 dns_name_getlabelsequence(keyname
, 0, n
- 1, keyname
);
707 static char hexdigits
[16] = {
708 '0', '1', '2', '3', '4', '5', '6', '7',
709 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
710 unsigned char randomdata
[16];
715 result
= isc_entropy_getdata(tctx
->ectx
,
719 if (result
!= ISC_R_SUCCESS
)
722 for (i
= 0, j
= 0; i
< sizeof(randomdata
); i
++) {
723 unsigned char val
= randomdata
[i
];
724 randomtext
[j
++] = hexdigits
[val
>> 4];
725 randomtext
[j
++] = hexdigits
[val
& 0xF];
727 isc_buffer_init(&b
, randomtext
, sizeof(randomtext
));
728 isc_buffer_add(&b
, sizeof(randomtext
));
729 result
= dns_name_fromtext(keyname
, &b
, NULL
, 0, NULL
);
730 if (result
!= ISC_R_SUCCESS
)
734 if (tkeyin
.mode
== DNS_TKEYMODE_GSSAPI
) {
735 /* Yup. This is a hack */
736 result
= dns_name_concatenate(keyname
, dns_rootname
,
738 if (result
!= ISC_R_SUCCESS
)
741 result
= dns_name_concatenate(keyname
, tctx
->domain
,
743 if (result
!= ISC_R_SUCCESS
)
747 result
= dns_tsigkey_find(&tsigkey
, keyname
, NULL
, ring
);
749 if (result
== ISC_R_SUCCESS
) {
750 tkeyout
.error
= dns_tsigerror_badname
;
751 dns_tsigkey_detach(&tsigkey
);
752 goto failure_with_tkey
;
753 } else if (result
!= ISC_R_NOTFOUND
)
758 switch (tkeyin
.mode
) {
759 case DNS_TKEYMODE_DIFFIEHELLMAN
:
760 tkeyout
.error
= dns_rcode_noerror
;
761 RETERR(process_dhtkey(msg
, signer
, keyname
, &tkeyin
,
762 tctx
, &tkeyout
, ring
,
765 case DNS_TKEYMODE_GSSAPI
:
766 tkeyout
.error
= dns_rcode_noerror
;
767 RETERR(process_gsstkey(msg
, signer
, keyname
, &tkeyin
,
768 tctx
, &tkeyout
, ring
,
772 case DNS_TKEYMODE_DELETE
:
773 tkeyout
.error
= dns_rcode_noerror
;
774 RETERR(process_deletetkey(msg
, signer
, keyname
,
778 case DNS_TKEYMODE_SERVERASSIGNED
:
779 case DNS_TKEYMODE_RESOLVERASSIGNED
:
780 result
= DNS_R_NOTIMP
;
783 tkeyout
.error
= dns_tsigerror_badmode
;
787 dns_rdata_init(&rdata
);
788 isc_buffer_init(&tkeyoutbuf
, tkeyoutdata
, sizeof(tkeyoutdata
));
789 result
= dns_rdata_fromstruct(&rdata
, tkeyout
.common
.rdclass
,
790 tkeyout
.common
.rdtype
, &tkeyout
,
794 dns_rdata_freestruct(&tkeyin
);
795 freetkeyin
= ISC_FALSE
;
798 if (tkeyout
.key
!= NULL
)
799 isc_mem_put(tkeyout
.mctx
, tkeyout
.key
, tkeyout
.keylen
);
800 if (tkeyout
.other
!= NULL
)
801 isc_mem_put(tkeyout
.mctx
, tkeyout
.other
, tkeyout
.otherlen
);
802 if (result
!= ISC_R_SUCCESS
)
805 RETERR(add_rdata_to_list(msg
, keyname
, &rdata
, 0, &namelist
));
807 RETERR(dns_message_reply(msg
, ISC_TRUE
));
809 name
= ISC_LIST_HEAD(namelist
);
810 while (name
!= NULL
) {
811 dns_name_t
*next
= ISC_LIST_NEXT(name
, link
);
812 ISC_LIST_UNLINK(namelist
, name
, link
);
813 dns_message_addname(msg
, name
, DNS_SECTION_ANSWER
);
817 return (ISC_R_SUCCESS
);
821 dns_rdata_freestruct(&tkeyin
);
822 if (!ISC_LIST_EMPTY(namelist
))
823 free_namelist(msg
, &namelist
);
828 buildquery(dns_message_t
*msg
, dns_name_t
*name
,
829 dns_rdata_tkey_t
*tkey
, isc_boolean_t win2k
)
831 dns_name_t
*qname
= NULL
, *aname
= NULL
;
832 dns_rdataset_t
*question
= NULL
, *tkeyset
= NULL
;
833 dns_rdatalist_t
*tkeylist
= NULL
;
834 dns_rdata_t
*rdata
= NULL
;
835 isc_buffer_t
*dynbuf
= NULL
;
838 REQUIRE(msg
!= NULL
);
839 REQUIRE(name
!= NULL
);
840 REQUIRE(tkey
!= NULL
);
842 RETERR(dns_message_gettempname(msg
, &qname
));
843 RETERR(dns_message_gettempname(msg
, &aname
));
845 RETERR(dns_message_gettemprdataset(msg
, &question
));
846 dns_rdataset_init(question
);
847 dns_rdataset_makequestion(question
, dns_rdataclass_any
,
850 RETERR(isc_buffer_allocate(msg
->mctx
, &dynbuf
, 4096));
851 RETERR(dns_message_gettemprdata(msg
, &rdata
));
853 RETERR(dns_rdata_fromstruct(rdata
, dns_rdataclass_any
,
854 dns_rdatatype_tkey
, tkey
, dynbuf
));
855 dns_message_takebuffer(msg
, &dynbuf
);
857 RETERR(dns_message_gettemprdatalist(msg
, &tkeylist
));
858 tkeylist
->rdclass
= dns_rdataclass_any
;
859 tkeylist
->type
= dns_rdatatype_tkey
;
860 tkeylist
->covers
= 0;
862 ISC_LIST_INIT(tkeylist
->rdata
);
863 ISC_LIST_APPEND(tkeylist
->rdata
, rdata
, link
);
865 RETERR(dns_message_gettemprdataset(msg
, &tkeyset
));
866 dns_rdataset_init(tkeyset
);
867 RETERR(dns_rdatalist_tordataset(tkeylist
, tkeyset
));
869 dns_name_init(qname
, NULL
);
870 dns_name_clone(name
, qname
);
872 dns_name_init(aname
, NULL
);
873 dns_name_clone(name
, aname
);
875 ISC_LIST_APPEND(qname
->list
, question
, link
);
876 ISC_LIST_APPEND(aname
->list
, tkeyset
, link
);
878 dns_message_addname(msg
, qname
, DNS_SECTION_QUESTION
);
881 * Windows 2000 needs this in the answer section, not the additional
882 * section where the RFC specifies.
885 dns_message_addname(msg
, aname
, DNS_SECTION_ANSWER
);
887 dns_message_addname(msg
, aname
, DNS_SECTION_ADDITIONAL
);
889 return (ISC_R_SUCCESS
);
893 dns_message_puttempname(msg
, &qname
);
895 dns_message_puttempname(msg
, &aname
);
896 if (question
!= NULL
) {
897 dns_rdataset_disassociate(question
);
898 dns_message_puttemprdataset(msg
, &question
);
901 isc_buffer_free(&dynbuf
);
902 printf("buildquery error\n");
907 dns_tkey_builddhquery(dns_message_t
*msg
, dst_key_t
*key
, dns_name_t
*name
,
908 dns_name_t
*algorithm
, isc_buffer_t
*nonce
,
909 isc_uint32_t lifetime
)
911 dns_rdata_tkey_t tkey
;
912 dns_rdata_t
*rdata
= NULL
;
913 isc_buffer_t
*dynbuf
= NULL
;
916 dns_namelist_t namelist
;
920 REQUIRE(msg
!= NULL
);
921 REQUIRE(key
!= NULL
);
922 REQUIRE(dst_key_alg(key
) == DNS_KEYALG_DH
);
923 REQUIRE(dst_key_isprivate(key
));
924 REQUIRE(name
!= NULL
);
925 REQUIRE(algorithm
!= NULL
);
927 tkey
.common
.rdclass
= dns_rdataclass_any
;
928 tkey
.common
.rdtype
= dns_rdatatype_tkey
;
929 ISC_LINK_INIT(&tkey
.common
, link
);
930 tkey
.mctx
= msg
->mctx
;
931 dns_name_init(&tkey
.algorithm
, NULL
);
932 dns_name_clone(algorithm
, &tkey
.algorithm
);
933 isc_stdtime_get(&now
);
934 tkey
.inception
= now
;
935 tkey
.expire
= now
+ lifetime
;
936 tkey
.mode
= DNS_TKEYMODE_DIFFIEHELLMAN
;
938 isc_buffer_usedregion(nonce
, &r
);
940 r
.base
= isc_mem_get(msg
->mctx
, 0);
945 tkey
.keylen
= r
.length
;
949 RETERR(buildquery(msg
, name
, &tkey
, ISC_FALSE
));
952 isc_mem_put(msg
->mctx
, r
.base
, 0);
954 RETERR(dns_message_gettemprdata(msg
, &rdata
));
955 RETERR(isc_buffer_allocate(msg
->mctx
, &dynbuf
, 1024));
956 RETERR(dst_key_todns(key
, dynbuf
));
957 isc_buffer_usedregion(dynbuf
, &r
);
958 dns_rdata_fromregion(rdata
, dns_rdataclass_any
,
959 dns_rdatatype_key
, &r
);
960 dns_message_takebuffer(msg
, &dynbuf
);
962 dns_name_init(&keyname
, NULL
);
963 dns_name_clone(dst_key_name(key
), &keyname
);
965 ISC_LIST_INIT(namelist
);
966 RETERR(add_rdata_to_list(msg
, &keyname
, rdata
, 0, &namelist
));
967 dns_message_addname(msg
, ISC_LIST_HEAD(namelist
),
968 DNS_SECTION_ADDITIONAL
);
970 return (ISC_R_SUCCESS
);
975 isc_buffer_free(&dynbuf
);
980 dns_tkey_buildgssquery(dns_message_t
*msg
, dns_name_t
*name
, dns_name_t
*gname
,
981 isc_buffer_t
*intoken
, isc_uint32_t lifetime
,
982 gss_ctx_id_t
*context
, isc_boolean_t win2k
)
984 dns_rdata_tkey_t tkey
;
988 unsigned char array
[4096];
992 REQUIRE(msg
!= NULL
);
993 REQUIRE(name
!= NULL
);
994 REQUIRE(gname
!= NULL
);
995 REQUIRE(context
!= NULL
);
997 isc_buffer_init(&token
, array
, sizeof(array
));
998 result
= dst_gssapi_initctx(gname
, NULL
, &token
, context
);
999 if (result
!= DNS_R_CONTINUE
&& result
!= ISC_R_SUCCESS
)
1002 tkey
.common
.rdclass
= dns_rdataclass_any
;
1003 tkey
.common
.rdtype
= dns_rdatatype_tkey
;
1004 ISC_LINK_INIT(&tkey
.common
, link
);
1006 dns_name_init(&tkey
.algorithm
, NULL
);
1009 dns_name_clone(DNS_TSIG_GSSAPIMS_NAME
, &tkey
.algorithm
);
1011 dns_name_clone(DNS_TSIG_GSSAPI_NAME
, &tkey
.algorithm
);
1013 isc_stdtime_get(&now
);
1014 tkey
.inception
= now
;
1015 tkey
.expire
= now
+ lifetime
;
1016 tkey
.mode
= DNS_TKEYMODE_GSSAPI
;
1018 tkey
.key
= isc_buffer_base(&token
);
1019 tkey
.keylen
= isc_buffer_usedlength(&token
);
1023 RETERR(buildquery(msg
, name
, &tkey
, win2k
));
1025 return (ISC_R_SUCCESS
);
1032 dns_tkey_builddeletequery(dns_message_t
*msg
, dns_tsigkey_t
*key
) {
1033 dns_rdata_tkey_t tkey
;
1035 REQUIRE(msg
!= NULL
);
1036 REQUIRE(key
!= NULL
);
1038 tkey
.common
.rdclass
= dns_rdataclass_any
;
1039 tkey
.common
.rdtype
= dns_rdatatype_tkey
;
1040 ISC_LINK_INIT(&tkey
.common
, link
);
1041 tkey
.mctx
= msg
->mctx
;
1042 dns_name_init(&tkey
.algorithm
, NULL
);
1043 dns_name_clone(key
->algorithm
, &tkey
.algorithm
);
1044 tkey
.inception
= tkey
.expire
= 0;
1045 tkey
.mode
= DNS_TKEYMODE_DELETE
;
1047 tkey
.keylen
= tkey
.otherlen
= 0;
1048 tkey
.key
= tkey
.other
= NULL
;
1050 return (buildquery(msg
, &key
->name
, &tkey
, ISC_FALSE
));
1054 find_tkey(dns_message_t
*msg
, dns_name_t
**name
, dns_rdata_t
*rdata
,
1057 dns_rdataset_t
*tkeyset
;
1058 isc_result_t result
;
1060 result
= dns_message_firstname(msg
, section
);
1061 while (result
== ISC_R_SUCCESS
) {
1063 dns_message_currentname(msg
, section
, name
);
1065 result
= dns_message_findtype(*name
, dns_rdatatype_tkey
, 0,
1067 if (result
== ISC_R_SUCCESS
) {
1068 result
= dns_rdataset_first(tkeyset
);
1069 if (result
!= ISC_R_SUCCESS
)
1071 dns_rdataset_current(tkeyset
, rdata
);
1072 return (ISC_R_SUCCESS
);
1074 result
= dns_message_nextname(msg
, section
);
1076 if (result
== ISC_R_NOMORE
)
1077 return (ISC_R_NOTFOUND
);
1082 dns_tkey_processdhresponse(dns_message_t
*qmsg
, dns_message_t
*rmsg
,
1083 dst_key_t
*key
, isc_buffer_t
*nonce
,
1084 dns_tsigkey_t
**outkey
, dns_tsig_keyring_t
*ring
)
1086 dns_rdata_t qtkeyrdata
= DNS_RDATA_INIT
, rtkeyrdata
= DNS_RDATA_INIT
;
1087 dns_name_t keyname
, *tkeyname
, *theirkeyname
, *ourkeyname
, *tempname
;
1088 dns_rdataset_t
*theirkeyset
= NULL
, *ourkeyset
= NULL
;
1089 dns_rdata_t theirkeyrdata
= DNS_RDATA_INIT
;
1090 dst_key_t
*theirkey
= NULL
;
1091 dns_rdata_tkey_t qtkey
, rtkey
;
1092 unsigned char secretdata
[256];
1093 unsigned int sharedsize
;
1094 isc_buffer_t
*shared
= NULL
, secret
;
1096 isc_result_t result
;
1097 isc_boolean_t freertkey
= ISC_FALSE
;
1099 REQUIRE(qmsg
!= NULL
);
1100 REQUIRE(rmsg
!= NULL
);
1101 REQUIRE(key
!= NULL
);
1102 REQUIRE(dst_key_alg(key
) == DNS_KEYALG_DH
);
1103 REQUIRE(dst_key_isprivate(key
));
1105 REQUIRE(*outkey
== NULL
);
1107 if (rmsg
->rcode
!= dns_rcode_noerror
)
1108 return (ISC_RESULTCLASS_DNSRCODE
+ rmsg
->rcode
);
1109 RETERR(find_tkey(rmsg
, &tkeyname
, &rtkeyrdata
, DNS_SECTION_ANSWER
));
1110 RETERR(dns_rdata_tostruct(&rtkeyrdata
, &rtkey
, NULL
));
1111 freertkey
= ISC_TRUE
;
1113 RETERR(find_tkey(qmsg
, &tempname
, &qtkeyrdata
,
1114 DNS_SECTION_ADDITIONAL
));
1115 RETERR(dns_rdata_tostruct(&qtkeyrdata
, &qtkey
, NULL
));
1117 if (rtkey
.error
!= dns_rcode_noerror
||
1118 rtkey
.mode
!= DNS_TKEYMODE_DIFFIEHELLMAN
||
1119 rtkey
.mode
!= qtkey
.mode
||
1120 !dns_name_equal(&rtkey
.algorithm
, &qtkey
.algorithm
) ||
1121 rmsg
->rcode
!= dns_rcode_noerror
) {
1122 tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
1124 result
= DNS_R_INVALIDTKEY
;
1125 dns_rdata_freestruct(&qtkey
);
1129 dns_rdata_freestruct(&qtkey
);
1131 dns_name_init(&keyname
, NULL
);
1132 dns_name_clone(dst_key_name(key
), &keyname
);
1136 RETERR(dns_message_findname(rmsg
, DNS_SECTION_ANSWER
, &keyname
,
1137 dns_rdatatype_key
, 0, &ourkeyname
,
1140 result
= dns_message_firstname(rmsg
, DNS_SECTION_ANSWER
);
1141 while (result
== ISC_R_SUCCESS
) {
1142 theirkeyname
= NULL
;
1143 dns_message_currentname(rmsg
, DNS_SECTION_ANSWER
,
1145 if (dns_name_equal(theirkeyname
, ourkeyname
))
1148 result
= dns_message_findtype(theirkeyname
, dns_rdatatype_key
,
1150 if (result
== ISC_R_SUCCESS
) {
1151 RETERR(dns_rdataset_first(theirkeyset
));
1155 result
= dns_message_nextname(rmsg
, DNS_SECTION_ANSWER
);
1158 if (theirkeyset
== NULL
) {
1159 tkey_log("dns_tkey_processdhresponse: failed to find server "
1161 result
= ISC_R_NOTFOUND
;
1165 dns_rdataset_current(theirkeyset
, &theirkeyrdata
);
1166 RETERR(dns_dnssec_keyfromrdata(theirkeyname
, &theirkeyrdata
,
1167 rmsg
->mctx
, &theirkey
));
1169 RETERR(dst_key_secretsize(key
, &sharedsize
));
1170 RETERR(isc_buffer_allocate(rmsg
->mctx
, &shared
, sharedsize
));
1172 RETERR(dst_key_computesecret(theirkey
, key
, shared
));
1174 isc_buffer_init(&secret
, secretdata
, sizeof(secretdata
));
1177 r
.length
= rtkey
.keylen
;
1179 isc_buffer_usedregion(nonce
, &r2
);
1181 r2
.base
= isc_mem_get(rmsg
->mctx
, 0);
1184 RETERR(compute_secret(shared
, &r2
, &r
, &secret
));
1186 isc_mem_put(rmsg
->mctx
, r2
.base
, 0);
1188 isc_buffer_usedregion(&secret
, &r
);
1189 result
= dns_tsigkey_create(tkeyname
, &rtkey
.algorithm
,
1190 r
.base
, r
.length
, ISC_TRUE
,
1191 NULL
, rtkey
.inception
, rtkey
.expire
,
1192 rmsg
->mctx
, ring
, outkey
);
1193 isc_buffer_free(&shared
);
1194 dns_rdata_freestruct(&rtkey
);
1195 dst_key_free(&theirkey
);
1200 isc_buffer_free(&shared
);
1202 if (theirkey
!= NULL
)
1203 dst_key_free(&theirkey
);
1206 dns_rdata_freestruct(&rtkey
);
1212 dns_tkey_processgssresponse(dns_message_t
*qmsg
, dns_message_t
*rmsg
,
1213 dns_name_t
*gname
, gss_ctx_id_t
*context
,
1214 isc_buffer_t
*outtoken
, dns_tsigkey_t
**outkey
,
1215 dns_tsig_keyring_t
*ring
)
1217 dns_rdata_t rtkeyrdata
= DNS_RDATA_INIT
, qtkeyrdata
= DNS_RDATA_INIT
;
1218 dns_name_t
*tkeyname
;
1219 dns_rdata_tkey_t rtkey
, qtkey
;
1220 dst_key_t
*dstkey
= NULL
;
1221 isc_buffer_t intoken
;
1222 isc_result_t result
;
1223 unsigned char array
[1024];
1225 REQUIRE(outtoken
!= NULL
);
1226 REQUIRE(qmsg
!= NULL
);
1227 REQUIRE(rmsg
!= NULL
);
1228 REQUIRE(gname
!= NULL
);
1230 REQUIRE(*outkey
== NULL
);
1232 if (rmsg
->rcode
!= dns_rcode_noerror
)
1233 return (ISC_RESULTCLASS_DNSRCODE
+ rmsg
->rcode
);
1234 RETERR(find_tkey(rmsg
, &tkeyname
, &rtkeyrdata
, DNS_SECTION_ANSWER
));
1235 RETERR(dns_rdata_tostruct(&rtkeyrdata
, &rtkey
, NULL
));
1238 * Win2k puts the item in the ANSWER section, while the RFC
1239 * specifies it should be in the ADDITIONAL section. Check first
1240 * where it should be, and then where it may be.
1242 result
= find_tkey(qmsg
, &tkeyname
, &qtkeyrdata
,
1243 DNS_SECTION_ADDITIONAL
);
1244 if (result
== ISC_R_NOTFOUND
)
1245 result
= find_tkey(qmsg
, &tkeyname
, &qtkeyrdata
,
1246 DNS_SECTION_ANSWER
);
1247 if (result
!= ISC_R_SUCCESS
)
1250 RETERR(dns_rdata_tostruct(&qtkeyrdata
, &qtkey
, NULL
));
1252 if (rtkey
.error
!= dns_rcode_noerror
||
1253 rtkey
.mode
!= DNS_TKEYMODE_GSSAPI
||
1254 !dns_name_equal(&rtkey
.algorithm
, &qtkey
.algorithm
)) {
1255 tkey_log("dns_tkey_processgssresponse: tkey mode invalid "
1256 "or error set(2) %d", rtkey
.error
);
1257 _dns_tkey_dumpmessage(qmsg
);
1258 _dns_tkey_dumpmessage(rmsg
);
1259 result
= DNS_R_INVALIDTKEY
;
1263 isc_buffer_init(outtoken
, array
, sizeof(array
));
1264 isc_buffer_init(&intoken
, rtkey
.key
, rtkey
.keylen
);
1265 RETERR(dst_gssapi_initctx(gname
, &intoken
, outtoken
, context
));
1268 RETERR(dst_key_fromgssapi(dns_rootname
, *context
, rmsg
->mctx
,
1271 RETERR(dns_tsigkey_createfromkey(tkeyname
, DNS_TSIG_GSSAPI_NAME
,
1272 dstkey
, ISC_FALSE
, NULL
,
1273 rtkey
.inception
, rtkey
.expire
,
1274 ring
->mctx
, ring
, outkey
));
1276 dns_rdata_freestruct(&rtkey
);
1281 * XXXSRA This probably leaks memory from rtkey and qtkey.
1287 dns_tkey_processdeleteresponse(dns_message_t
*qmsg
, dns_message_t
*rmsg
,
1288 dns_tsig_keyring_t
*ring
)
1290 dns_rdata_t qtkeyrdata
= DNS_RDATA_INIT
, rtkeyrdata
= DNS_RDATA_INIT
;
1291 dns_name_t
*tkeyname
, *tempname
;
1292 dns_rdata_tkey_t qtkey
, rtkey
;
1293 dns_tsigkey_t
*tsigkey
= NULL
;
1294 isc_result_t result
;
1296 REQUIRE(qmsg
!= NULL
);
1297 REQUIRE(rmsg
!= NULL
);
1299 if (rmsg
->rcode
!= dns_rcode_noerror
)
1300 return(ISC_RESULTCLASS_DNSRCODE
+ rmsg
->rcode
);
1302 RETERR(find_tkey(rmsg
, &tkeyname
, &rtkeyrdata
, DNS_SECTION_ANSWER
));
1303 RETERR(dns_rdata_tostruct(&rtkeyrdata
, &rtkey
, NULL
));
1305 RETERR(find_tkey(qmsg
, &tempname
, &qtkeyrdata
,
1306 DNS_SECTION_ADDITIONAL
));
1307 RETERR(dns_rdata_tostruct(&qtkeyrdata
, &qtkey
, NULL
));
1309 if (rtkey
.error
!= dns_rcode_noerror
||
1310 rtkey
.mode
!= DNS_TKEYMODE_DELETE
||
1311 rtkey
.mode
!= qtkey
.mode
||
1312 !dns_name_equal(&rtkey
.algorithm
, &qtkey
.algorithm
) ||
1313 rmsg
->rcode
!= dns_rcode_noerror
) {
1314 tkey_log("dns_tkey_processdeleteresponse: tkey mode invalid "
1316 result
= DNS_R_INVALIDTKEY
;
1317 dns_rdata_freestruct(&qtkey
);
1318 dns_rdata_freestruct(&rtkey
);
1322 dns_rdata_freestruct(&qtkey
);
1324 RETERR(dns_tsigkey_find(&tsigkey
, tkeyname
, &rtkey
.algorithm
, ring
));
1326 dns_rdata_freestruct(&rtkey
);
1329 * Mark the key as deleted.
1331 dns_tsigkey_setdeleted(tsigkey
);
1333 * Release the reference.
1335 dns_tsigkey_detach(&tsigkey
);
1342 dns_tkey_gssnegotiate(dns_message_t
*qmsg
, dns_message_t
*rmsg
,
1343 dns_name_t
*server
, gss_ctx_id_t
*context
,
1344 dns_tsigkey_t
**outkey
, dns_tsig_keyring_t
*ring
,
1345 isc_boolean_t win2k
)
1347 dns_rdata_t rtkeyrdata
= DNS_RDATA_INIT
, qtkeyrdata
= DNS_RDATA_INIT
;
1348 dns_name_t
*tkeyname
;
1349 dns_rdata_tkey_t rtkey
, qtkey
;
1350 isc_buffer_t intoken
, outtoken
;
1351 dst_key_t
*dstkey
= NULL
;
1352 isc_result_t result
;
1353 unsigned char array
[1024];
1355 REQUIRE(qmsg
!= NULL
);
1356 REQUIRE(rmsg
!= NULL
);
1357 REQUIRE(server
!= NULL
);
1359 REQUIRE(*outkey
== NULL
);
1361 if (rmsg
->rcode
!= dns_rcode_noerror
)
1362 return (ISC_RESULTCLASS_DNSRCODE
+ rmsg
->rcode
);
1364 RETERR(find_tkey(rmsg
, &tkeyname
, &rtkeyrdata
, DNS_SECTION_ANSWER
));
1365 RETERR(dns_rdata_tostruct(&rtkeyrdata
, &rtkey
, NULL
));
1367 if (win2k
== ISC_TRUE
)
1368 RETERR(find_tkey(qmsg
, &tkeyname
, &qtkeyrdata
,
1369 DNS_SECTION_ANSWER
));
1371 RETERR(find_tkey(qmsg
, &tkeyname
, &qtkeyrdata
,
1372 DNS_SECTION_ADDITIONAL
));
1374 RETERR(dns_rdata_tostruct(&qtkeyrdata
, &qtkey
, NULL
));
1376 if (rtkey
.error
!= dns_rcode_noerror
||
1377 rtkey
.mode
!= DNS_TKEYMODE_GSSAPI
||
1378 !dns_name_equal(&rtkey
.algorithm
, &qtkey
.algorithm
))
1380 tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
1382 result
= DNS_R_INVALIDTKEY
;
1386 isc_buffer_init(&intoken
, rtkey
.key
, rtkey
.keylen
);
1387 isc_buffer_init(&outtoken
, array
, sizeof(array
));
1389 result
= dst_gssapi_initctx(server
, &intoken
, &outtoken
, context
);
1390 if (result
!= DNS_R_CONTINUE
&& result
!= ISC_R_SUCCESS
)
1394 RETERR(dst_key_fromgssapi(dns_rootname
, *context
, rmsg
->mctx
,
1398 * XXXSRA This seems confused. If we got CONTINUE from initctx,
1399 * the GSS negotiation hasn't completed yet, so we can't sign
1403 RETERR(dns_tsigkey_createfromkey(tkeyname
,
1405 ? DNS_TSIG_GSSAPIMS_NAME
1406 : DNS_TSIG_GSSAPI_NAME
),
1407 dstkey
, ISC_TRUE
, NULL
,
1408 rtkey
.inception
, rtkey
.expire
,
1409 ring
->mctx
, ring
, outkey
));
1411 dns_rdata_freestruct(&rtkey
);
1416 * XXXSRA This probably leaks memory from qtkey.
1418 dns_rdata_freestruct(&rtkey
);