1*00b67f09SDavid van Moolenbroek /* $NetBSD: tkey.c,v 1.9 2015/07/28 18:55:16 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek * Copyright (C) 1999-2001, 2003 Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek *
7*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek *
11*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek */
19*00b67f09SDavid van Moolenbroek
20*00b67f09SDavid van Moolenbroek /*
21*00b67f09SDavid van Moolenbroek * Id
22*00b67f09SDavid van Moolenbroek */
23*00b67f09SDavid van Moolenbroek /*! \file */
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek
26*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
27*00b67f09SDavid van Moolenbroek #include <isc/entropy.h>
28*00b67f09SDavid van Moolenbroek #include <isc/md5.h>
29*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
30*00b67f09SDavid van Moolenbroek #include <isc/string.h>
31*00b67f09SDavid van Moolenbroek #include <isc/util.h>
32*00b67f09SDavid van Moolenbroek
33*00b67f09SDavid van Moolenbroek #include <dns/dnssec.h>
34*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
35*00b67f09SDavid van Moolenbroek #include <dns/keyvalues.h>
36*00b67f09SDavid van Moolenbroek #include <dns/log.h>
37*00b67f09SDavid van Moolenbroek #include <dns/message.h>
38*00b67f09SDavid van Moolenbroek #include <dns/name.h>
39*00b67f09SDavid van Moolenbroek #include <dns/rdata.h>
40*00b67f09SDavid van Moolenbroek #include <dns/rdatalist.h>
41*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
42*00b67f09SDavid van Moolenbroek #include <dns/rdatastruct.h>
43*00b67f09SDavid van Moolenbroek #include <dns/result.h>
44*00b67f09SDavid van Moolenbroek #include <dns/tkey.h>
45*00b67f09SDavid van Moolenbroek #include <dns/tsig.h>
46*00b67f09SDavid van Moolenbroek
47*00b67f09SDavid van Moolenbroek #include <dst/dst.h>
48*00b67f09SDavid van Moolenbroek #include <dst/gssapi.h>
49*00b67f09SDavid van Moolenbroek
50*00b67f09SDavid van Moolenbroek #include "dst_internal.h"
51*00b67f09SDavid van Moolenbroek
52*00b67f09SDavid van Moolenbroek #define TKEY_RANDOM_AMOUNT 16
53*00b67f09SDavid van Moolenbroek
54*00b67f09SDavid van Moolenbroek #ifdef PKCS11CRYPTO
55*00b67f09SDavid van Moolenbroek #include <pk11/pk11.h>
56*00b67f09SDavid van Moolenbroek #endif
57*00b67f09SDavid van Moolenbroek
58*00b67f09SDavid van Moolenbroek #define RETERR(x) do { \
59*00b67f09SDavid van Moolenbroek result = (x); \
60*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) \
61*00b67f09SDavid van Moolenbroek goto failure; \
62*00b67f09SDavid van Moolenbroek } while (/*CONSTCOND*/0)
63*00b67f09SDavid van Moolenbroek
64*00b67f09SDavid van Moolenbroek static void
65*00b67f09SDavid van Moolenbroek tkey_log(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2);
66*00b67f09SDavid van Moolenbroek
67*00b67f09SDavid van Moolenbroek static void
tkey_log(const char * fmt,...)68*00b67f09SDavid van Moolenbroek tkey_log(const char *fmt, ...) {
69*00b67f09SDavid van Moolenbroek va_list ap;
70*00b67f09SDavid van Moolenbroek
71*00b67f09SDavid van Moolenbroek va_start(ap, fmt);
72*00b67f09SDavid van Moolenbroek isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
73*00b67f09SDavid van Moolenbroek DNS_LOGMODULE_REQUEST, ISC_LOG_DEBUG(4), fmt, ap);
74*00b67f09SDavid van Moolenbroek va_end(ap);
75*00b67f09SDavid van Moolenbroek }
76*00b67f09SDavid van Moolenbroek
77*00b67f09SDavid van Moolenbroek static void
_dns_tkey_dumpmessage(dns_message_t * msg)78*00b67f09SDavid van Moolenbroek _dns_tkey_dumpmessage(dns_message_t *msg) {
79*00b67f09SDavid van Moolenbroek isc_buffer_t outbuf;
80*00b67f09SDavid van Moolenbroek unsigned char output[4096];
81*00b67f09SDavid van Moolenbroek isc_result_t result;
82*00b67f09SDavid van Moolenbroek
83*00b67f09SDavid van Moolenbroek isc_buffer_init(&outbuf, output, sizeof(output));
84*00b67f09SDavid van Moolenbroek result = dns_message_totext(msg, &dns_master_style_debug, 0,
85*00b67f09SDavid van Moolenbroek &outbuf);
86*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
87*00b67f09SDavid van Moolenbroek fprintf(stderr, "Warning: dns_message_totext returned: %s\n",
88*00b67f09SDavid van Moolenbroek dns_result_totext(result));
89*00b67f09SDavid van Moolenbroek fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&outbuf),
90*00b67f09SDavid van Moolenbroek (char *)isc_buffer_base(&outbuf));
91*00b67f09SDavid van Moolenbroek }
92*00b67f09SDavid van Moolenbroek
93*00b67f09SDavid van Moolenbroek isc_result_t
dns_tkeyctx_create(isc_mem_t * mctx,isc_entropy_t * ectx,dns_tkeyctx_t ** tctxp)94*00b67f09SDavid van Moolenbroek dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
95*00b67f09SDavid van Moolenbroek {
96*00b67f09SDavid van Moolenbroek dns_tkeyctx_t *tctx;
97*00b67f09SDavid van Moolenbroek
98*00b67f09SDavid van Moolenbroek REQUIRE(mctx != NULL);
99*00b67f09SDavid van Moolenbroek REQUIRE(ectx != NULL);
100*00b67f09SDavid van Moolenbroek REQUIRE(tctxp != NULL && *tctxp == NULL);
101*00b67f09SDavid van Moolenbroek
102*00b67f09SDavid van Moolenbroek tctx = isc_mem_get(mctx, sizeof(dns_tkeyctx_t));
103*00b67f09SDavid van Moolenbroek if (tctx == NULL)
104*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
105*00b67f09SDavid van Moolenbroek tctx->mctx = NULL;
106*00b67f09SDavid van Moolenbroek isc_mem_attach(mctx, &tctx->mctx);
107*00b67f09SDavid van Moolenbroek tctx->ectx = NULL;
108*00b67f09SDavid van Moolenbroek isc_entropy_attach(ectx, &tctx->ectx);
109*00b67f09SDavid van Moolenbroek tctx->dhkey = NULL;
110*00b67f09SDavid van Moolenbroek tctx->domain = NULL;
111*00b67f09SDavid van Moolenbroek tctx->gsscred = NULL;
112*00b67f09SDavid van Moolenbroek tctx->gssapi_keytab = NULL;
113*00b67f09SDavid van Moolenbroek
114*00b67f09SDavid van Moolenbroek *tctxp = tctx;
115*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
116*00b67f09SDavid van Moolenbroek }
117*00b67f09SDavid van Moolenbroek
118*00b67f09SDavid van Moolenbroek void
dns_tkeyctx_destroy(dns_tkeyctx_t ** tctxp)119*00b67f09SDavid van Moolenbroek dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp) {
120*00b67f09SDavid van Moolenbroek isc_mem_t *mctx;
121*00b67f09SDavid van Moolenbroek dns_tkeyctx_t *tctx;
122*00b67f09SDavid van Moolenbroek
123*00b67f09SDavid van Moolenbroek REQUIRE(tctxp != NULL && *tctxp != NULL);
124*00b67f09SDavid van Moolenbroek
125*00b67f09SDavid van Moolenbroek tctx = *tctxp;
126*00b67f09SDavid van Moolenbroek mctx = tctx->mctx;
127*00b67f09SDavid van Moolenbroek
128*00b67f09SDavid van Moolenbroek if (tctx->dhkey != NULL)
129*00b67f09SDavid van Moolenbroek dst_key_free(&tctx->dhkey);
130*00b67f09SDavid van Moolenbroek if (tctx->domain != NULL) {
131*00b67f09SDavid van Moolenbroek if (dns_name_dynamic(tctx->domain))
132*00b67f09SDavid van Moolenbroek dns_name_free(tctx->domain, mctx);
133*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t));
134*00b67f09SDavid van Moolenbroek }
135*00b67f09SDavid van Moolenbroek if (tctx->gssapi_keytab != NULL) {
136*00b67f09SDavid van Moolenbroek isc_mem_free(mctx, tctx->gssapi_keytab);
137*00b67f09SDavid van Moolenbroek }
138*00b67f09SDavid van Moolenbroek if (tctx->gsscred != NULL)
139*00b67f09SDavid van Moolenbroek dst_gssapi_releasecred(&tctx->gsscred);
140*00b67f09SDavid van Moolenbroek isc_entropy_detach(&tctx->ectx);
141*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, tctx, sizeof(dns_tkeyctx_t));
142*00b67f09SDavid van Moolenbroek isc_mem_detach(&mctx);
143*00b67f09SDavid van Moolenbroek *tctxp = NULL;
144*00b67f09SDavid van Moolenbroek }
145*00b67f09SDavid van Moolenbroek
146*00b67f09SDavid van Moolenbroek static isc_result_t
add_rdata_to_list(dns_message_t * msg,dns_name_t * name,dns_rdata_t * rdata,isc_uint32_t ttl,dns_namelist_t * namelist)147*00b67f09SDavid van Moolenbroek add_rdata_to_list(dns_message_t *msg, dns_name_t *name, dns_rdata_t *rdata,
148*00b67f09SDavid van Moolenbroek isc_uint32_t ttl, dns_namelist_t *namelist)
149*00b67f09SDavid van Moolenbroek {
150*00b67f09SDavid van Moolenbroek isc_result_t result;
151*00b67f09SDavid van Moolenbroek isc_region_t r, newr;
152*00b67f09SDavid van Moolenbroek dns_rdata_t *newrdata = NULL;
153*00b67f09SDavid van Moolenbroek dns_name_t *newname = NULL;
154*00b67f09SDavid van Moolenbroek dns_rdatalist_t *newlist = NULL;
155*00b67f09SDavid van Moolenbroek dns_rdataset_t *newset = NULL;
156*00b67f09SDavid van Moolenbroek isc_buffer_t *tmprdatabuf = NULL;
157*00b67f09SDavid van Moolenbroek
158*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettemprdata(msg, &newrdata));
159*00b67f09SDavid van Moolenbroek
160*00b67f09SDavid van Moolenbroek dns_rdata_toregion(rdata, &r);
161*00b67f09SDavid van Moolenbroek RETERR(isc_buffer_allocate(msg->mctx, &tmprdatabuf, r.length));
162*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(tmprdatabuf, &newr);
163*00b67f09SDavid van Moolenbroek memmove(newr.base, r.base, r.length);
164*00b67f09SDavid van Moolenbroek dns_rdata_fromregion(newrdata, rdata->rdclass, rdata->type, &newr);
165*00b67f09SDavid van Moolenbroek dns_message_takebuffer(msg, &tmprdatabuf);
166*00b67f09SDavid van Moolenbroek
167*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettempname(msg, &newname));
168*00b67f09SDavid van Moolenbroek dns_name_init(newname, NULL);
169*00b67f09SDavid van Moolenbroek RETERR(dns_name_dup(name, msg->mctx, newname));
170*00b67f09SDavid van Moolenbroek
171*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettemprdatalist(msg, &newlist));
172*00b67f09SDavid van Moolenbroek newlist->rdclass = newrdata->rdclass;
173*00b67f09SDavid van Moolenbroek newlist->type = newrdata->type;
174*00b67f09SDavid van Moolenbroek newlist->covers = 0;
175*00b67f09SDavid van Moolenbroek newlist->ttl = ttl;
176*00b67f09SDavid van Moolenbroek ISC_LIST_INIT(newlist->rdata);
177*00b67f09SDavid van Moolenbroek ISC_LIST_APPEND(newlist->rdata, newrdata, link);
178*00b67f09SDavid van Moolenbroek
179*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettemprdataset(msg, &newset));
180*00b67f09SDavid van Moolenbroek RETERR(dns_rdatalist_tordataset(newlist, newset));
181*00b67f09SDavid van Moolenbroek
182*00b67f09SDavid van Moolenbroek ISC_LIST_INIT(newname->list);
183*00b67f09SDavid van Moolenbroek ISC_LIST_APPEND(newname->list, newset, link);
184*00b67f09SDavid van Moolenbroek
185*00b67f09SDavid van Moolenbroek ISC_LIST_APPEND(*namelist, newname, link);
186*00b67f09SDavid van Moolenbroek
187*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
188*00b67f09SDavid van Moolenbroek
189*00b67f09SDavid van Moolenbroek failure:
190*00b67f09SDavid van Moolenbroek if (newrdata != NULL) {
191*00b67f09SDavid van Moolenbroek if (ISC_LINK_LINKED(newrdata, link)) {
192*00b67f09SDavid van Moolenbroek INSIST(newlist != NULL);
193*00b67f09SDavid van Moolenbroek ISC_LIST_UNLINK(newlist->rdata, newrdata, link);
194*00b67f09SDavid van Moolenbroek }
195*00b67f09SDavid van Moolenbroek dns_message_puttemprdata(msg, &newrdata);
196*00b67f09SDavid van Moolenbroek }
197*00b67f09SDavid van Moolenbroek if (newname != NULL)
198*00b67f09SDavid van Moolenbroek dns_message_puttempname(msg, &newname);
199*00b67f09SDavid van Moolenbroek if (newset != NULL) {
200*00b67f09SDavid van Moolenbroek dns_rdataset_disassociate(newset);
201*00b67f09SDavid van Moolenbroek dns_message_puttemprdataset(msg, &newset);
202*00b67f09SDavid van Moolenbroek }
203*00b67f09SDavid van Moolenbroek if (newlist != NULL)
204*00b67f09SDavid van Moolenbroek dns_message_puttemprdatalist(msg, &newlist);
205*00b67f09SDavid van Moolenbroek return (result);
206*00b67f09SDavid van Moolenbroek }
207*00b67f09SDavid van Moolenbroek
208*00b67f09SDavid van Moolenbroek static void
free_namelist(dns_message_t * msg,dns_namelist_t * namelist)209*00b67f09SDavid van Moolenbroek free_namelist(dns_message_t *msg, dns_namelist_t *namelist) {
210*00b67f09SDavid van Moolenbroek dns_name_t *name;
211*00b67f09SDavid van Moolenbroek dns_rdataset_t *set;
212*00b67f09SDavid van Moolenbroek
213*00b67f09SDavid van Moolenbroek while (!ISC_LIST_EMPTY(*namelist)) {
214*00b67f09SDavid van Moolenbroek name = ISC_LIST_HEAD(*namelist);
215*00b67f09SDavid van Moolenbroek ISC_LIST_UNLINK(*namelist, name, link);
216*00b67f09SDavid van Moolenbroek while (!ISC_LIST_EMPTY(name->list)) {
217*00b67f09SDavid van Moolenbroek set = ISC_LIST_HEAD(name->list);
218*00b67f09SDavid van Moolenbroek ISC_LIST_UNLINK(name->list, set, link);
219*00b67f09SDavid van Moolenbroek dns_message_puttemprdataset(msg, &set);
220*00b67f09SDavid van Moolenbroek }
221*00b67f09SDavid van Moolenbroek dns_message_puttempname(msg, &name);
222*00b67f09SDavid van Moolenbroek }
223*00b67f09SDavid van Moolenbroek }
224*00b67f09SDavid van Moolenbroek
225*00b67f09SDavid van Moolenbroek static isc_result_t
compute_secret(isc_buffer_t * shared,isc_region_t * queryrandomness,isc_region_t * serverrandomness,isc_buffer_t * secret)226*00b67f09SDavid van Moolenbroek compute_secret(isc_buffer_t *shared, isc_region_t *queryrandomness,
227*00b67f09SDavid van Moolenbroek isc_region_t *serverrandomness, isc_buffer_t *secret)
228*00b67f09SDavid van Moolenbroek {
229*00b67f09SDavid van Moolenbroek isc_md5_t md5ctx;
230*00b67f09SDavid van Moolenbroek isc_region_t r, r2;
231*00b67f09SDavid van Moolenbroek unsigned char digests[32];
232*00b67f09SDavid van Moolenbroek unsigned int i;
233*00b67f09SDavid van Moolenbroek
234*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(shared, &r);
235*00b67f09SDavid van Moolenbroek
236*00b67f09SDavid van Moolenbroek /*
237*00b67f09SDavid van Moolenbroek * MD5 ( query data | DH value ).
238*00b67f09SDavid van Moolenbroek */
239*00b67f09SDavid van Moolenbroek isc_md5_init(&md5ctx);
240*00b67f09SDavid van Moolenbroek isc_md5_update(&md5ctx, queryrandomness->base,
241*00b67f09SDavid van Moolenbroek queryrandomness->length);
242*00b67f09SDavid van Moolenbroek isc_md5_update(&md5ctx, r.base, r.length);
243*00b67f09SDavid van Moolenbroek isc_md5_final(&md5ctx, digests);
244*00b67f09SDavid van Moolenbroek
245*00b67f09SDavid van Moolenbroek /*
246*00b67f09SDavid van Moolenbroek * MD5 ( server data | DH value ).
247*00b67f09SDavid van Moolenbroek */
248*00b67f09SDavid van Moolenbroek isc_md5_init(&md5ctx);
249*00b67f09SDavid van Moolenbroek isc_md5_update(&md5ctx, serverrandomness->base,
250*00b67f09SDavid van Moolenbroek serverrandomness->length);
251*00b67f09SDavid van Moolenbroek isc_md5_update(&md5ctx, r.base, r.length);
252*00b67f09SDavid van Moolenbroek isc_md5_final(&md5ctx, &digests[ISC_MD5_DIGESTLENGTH]);
253*00b67f09SDavid van Moolenbroek
254*00b67f09SDavid van Moolenbroek /*
255*00b67f09SDavid van Moolenbroek * XOR ( DH value, MD5-1 | MD5-2).
256*00b67f09SDavid van Moolenbroek */
257*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(secret, &r);
258*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(shared, &r2);
259*00b67f09SDavid van Moolenbroek if (r.length < sizeof(digests) || r.length < r2.length)
260*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
261*00b67f09SDavid van Moolenbroek if (r2.length > sizeof(digests)) {
262*00b67f09SDavid van Moolenbroek memmove(r.base, r2.base, r2.length);
263*00b67f09SDavid van Moolenbroek for (i = 0; i < sizeof(digests); i++)
264*00b67f09SDavid van Moolenbroek r.base[i] ^= digests[i];
265*00b67f09SDavid van Moolenbroek isc_buffer_add(secret, r2.length);
266*00b67f09SDavid van Moolenbroek } else {
267*00b67f09SDavid van Moolenbroek memmove(r.base, digests, sizeof(digests));
268*00b67f09SDavid van Moolenbroek for (i = 0; i < r2.length; i++)
269*00b67f09SDavid van Moolenbroek r.base[i] ^= r2.base[i];
270*00b67f09SDavid van Moolenbroek isc_buffer_add(secret, sizeof(digests));
271*00b67f09SDavid van Moolenbroek }
272*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
273*00b67f09SDavid van Moolenbroek
274*00b67f09SDavid van Moolenbroek }
275*00b67f09SDavid van Moolenbroek
276*00b67f09SDavid van Moolenbroek static isc_result_t
process_dhtkey(dns_message_t * msg,dns_name_t * signer,dns_name_t * name,dns_rdata_tkey_t * tkeyin,dns_tkeyctx_t * tctx,dns_rdata_tkey_t * tkeyout,dns_tsig_keyring_t * ring,dns_namelist_t * namelist)277*00b67f09SDavid van Moolenbroek process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
278*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx,
279*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t *tkeyout,
280*00b67f09SDavid van Moolenbroek dns_tsig_keyring_t *ring, dns_namelist_t *namelist)
281*00b67f09SDavid van Moolenbroek {
282*00b67f09SDavid van Moolenbroek isc_result_t result = ISC_R_SUCCESS;
283*00b67f09SDavid van Moolenbroek dns_name_t *keyname, ourname;
284*00b67f09SDavid van Moolenbroek dns_rdataset_t *keyset = NULL;
285*00b67f09SDavid van Moolenbroek dns_rdata_t keyrdata = DNS_RDATA_INIT, ourkeyrdata = DNS_RDATA_INIT;
286*00b67f09SDavid van Moolenbroek isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE;
287*00b67f09SDavid van Moolenbroek dst_key_t *pubkey = NULL;
288*00b67f09SDavid van Moolenbroek isc_buffer_t ourkeybuf, *shared = NULL;
289*00b67f09SDavid van Moolenbroek isc_region_t r, r2, ourkeyr;
290*00b67f09SDavid van Moolenbroek unsigned char keydata[DST_KEY_MAXSIZE];
291*00b67f09SDavid van Moolenbroek unsigned int sharedsize;
292*00b67f09SDavid van Moolenbroek isc_buffer_t secret;
293*00b67f09SDavid van Moolenbroek unsigned char *randomdata = NULL, secretdata[256];
294*00b67f09SDavid van Moolenbroek dns_ttl_t ttl = 0;
295*00b67f09SDavid van Moolenbroek
296*00b67f09SDavid van Moolenbroek if (tctx->dhkey == NULL) {
297*00b67f09SDavid van Moolenbroek tkey_log("process_dhtkey: tkey-dhkey not defined");
298*00b67f09SDavid van Moolenbroek tkeyout->error = dns_tsigerror_badalg;
299*00b67f09SDavid van Moolenbroek return (DNS_R_REFUSED);
300*00b67f09SDavid van Moolenbroek }
301*00b67f09SDavid van Moolenbroek
302*00b67f09SDavid van Moolenbroek if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) {
303*00b67f09SDavid van Moolenbroek tkey_log("process_dhtkey: algorithms other than "
304*00b67f09SDavid van Moolenbroek "hmac-md5 are not supported");
305*00b67f09SDavid van Moolenbroek tkeyout->error = dns_tsigerror_badalg;
306*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
307*00b67f09SDavid van Moolenbroek }
308*00b67f09SDavid van Moolenbroek
309*00b67f09SDavid van Moolenbroek /*
310*00b67f09SDavid van Moolenbroek * Look for a DH KEY record that will work with ours.
311*00b67f09SDavid van Moolenbroek */
312*00b67f09SDavid van Moolenbroek for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL);
313*00b67f09SDavid van Moolenbroek result == ISC_R_SUCCESS && !found_key;
314*00b67f09SDavid van Moolenbroek result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL)) {
315*00b67f09SDavid van Moolenbroek keyname = NULL;
316*00b67f09SDavid van Moolenbroek dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname);
317*00b67f09SDavid van Moolenbroek keyset = NULL;
318*00b67f09SDavid van Moolenbroek result = dns_message_findtype(keyname, dns_rdatatype_key, 0,
319*00b67f09SDavid van Moolenbroek &keyset);
320*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
321*00b67f09SDavid van Moolenbroek continue;
322*00b67f09SDavid van Moolenbroek
323*00b67f09SDavid van Moolenbroek for (result = dns_rdataset_first(keyset);
324*00b67f09SDavid van Moolenbroek result == ISC_R_SUCCESS && !found_key;
325*00b67f09SDavid van Moolenbroek result = dns_rdataset_next(keyset)) {
326*00b67f09SDavid van Moolenbroek dns_rdataset_current(keyset, &keyrdata);
327*00b67f09SDavid van Moolenbroek pubkey = NULL;
328*00b67f09SDavid van Moolenbroek result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
329*00b67f09SDavid van Moolenbroek msg->mctx, &pubkey);
330*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
331*00b67f09SDavid van Moolenbroek dns_rdata_reset(&keyrdata);
332*00b67f09SDavid van Moolenbroek continue;
333*00b67f09SDavid van Moolenbroek }
334*00b67f09SDavid van Moolenbroek if (dst_key_alg(pubkey) == DNS_KEYALG_DH) {
335*00b67f09SDavid van Moolenbroek if (dst_key_paramcompare(pubkey, tctx->dhkey))
336*00b67f09SDavid van Moolenbroek {
337*00b67f09SDavid van Moolenbroek found_key = ISC_TRUE;
338*00b67f09SDavid van Moolenbroek ttl = keyset->ttl;
339*00b67f09SDavid van Moolenbroek break;
340*00b67f09SDavid van Moolenbroek } else
341*00b67f09SDavid van Moolenbroek found_incompatible = ISC_TRUE;
342*00b67f09SDavid van Moolenbroek }
343*00b67f09SDavid van Moolenbroek dst_key_free(&pubkey);
344*00b67f09SDavid van Moolenbroek dns_rdata_reset(&keyrdata);
345*00b67f09SDavid van Moolenbroek }
346*00b67f09SDavid van Moolenbroek }
347*00b67f09SDavid van Moolenbroek
348*00b67f09SDavid van Moolenbroek if (!found_key) {
349*00b67f09SDavid van Moolenbroek if (found_incompatible) {
350*00b67f09SDavid van Moolenbroek tkey_log("process_dhtkey: found an incompatible key");
351*00b67f09SDavid van Moolenbroek tkeyout->error = dns_tsigerror_badkey;
352*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
353*00b67f09SDavid van Moolenbroek } else {
354*00b67f09SDavid van Moolenbroek tkey_log("process_dhtkey: failed to find a key");
355*00b67f09SDavid van Moolenbroek return (DNS_R_FORMERR);
356*00b67f09SDavid van Moolenbroek }
357*00b67f09SDavid van Moolenbroek }
358*00b67f09SDavid van Moolenbroek
359*00b67f09SDavid van Moolenbroek RETERR(add_rdata_to_list(msg, keyname, &keyrdata, ttl, namelist));
360*00b67f09SDavid van Moolenbroek
361*00b67f09SDavid van Moolenbroek isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata));
362*00b67f09SDavid van Moolenbroek RETERR(dst_key_todns(tctx->dhkey, &ourkeybuf));
363*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(&ourkeybuf, &ourkeyr);
364*00b67f09SDavid van Moolenbroek dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_any,
365*00b67f09SDavid van Moolenbroek dns_rdatatype_key, &ourkeyr);
366*00b67f09SDavid van Moolenbroek
367*00b67f09SDavid van Moolenbroek dns_name_init(&ourname, NULL);
368*00b67f09SDavid van Moolenbroek dns_name_clone(dst_key_name(tctx->dhkey), &ourname);
369*00b67f09SDavid van Moolenbroek
370*00b67f09SDavid van Moolenbroek /*
371*00b67f09SDavid van Moolenbroek * XXXBEW The TTL should be obtained from the database, if it exists.
372*00b67f09SDavid van Moolenbroek */
373*00b67f09SDavid van Moolenbroek RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, 0, namelist));
374*00b67f09SDavid van Moolenbroek
375*00b67f09SDavid van Moolenbroek RETERR(dst_key_secretsize(tctx->dhkey, &sharedsize));
376*00b67f09SDavid van Moolenbroek RETERR(isc_buffer_allocate(msg->mctx, &shared, sharedsize));
377*00b67f09SDavid van Moolenbroek
378*00b67f09SDavid van Moolenbroek result = dst_key_computesecret(pubkey, tctx->dhkey, shared);
379*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
380*00b67f09SDavid van Moolenbroek tkey_log("process_dhtkey: failed to compute shared secret: %s",
381*00b67f09SDavid van Moolenbroek isc_result_totext(result));
382*00b67f09SDavid van Moolenbroek goto failure;
383*00b67f09SDavid van Moolenbroek }
384*00b67f09SDavid van Moolenbroek dst_key_free(&pubkey);
385*00b67f09SDavid van Moolenbroek
386*00b67f09SDavid van Moolenbroek isc_buffer_init(&secret, secretdata, sizeof(secretdata));
387*00b67f09SDavid van Moolenbroek
388*00b67f09SDavid van Moolenbroek randomdata = isc_mem_get(tkeyout->mctx, TKEY_RANDOM_AMOUNT);
389*00b67f09SDavid van Moolenbroek if (randomdata == NULL)
390*00b67f09SDavid van Moolenbroek goto failure;
391*00b67f09SDavid van Moolenbroek
392*00b67f09SDavid van Moolenbroek result = dst__entropy_getdata(randomdata, TKEY_RANDOM_AMOUNT,
393*00b67f09SDavid van Moolenbroek ISC_FALSE);
394*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
395*00b67f09SDavid van Moolenbroek tkey_log("process_dhtkey: failed to obtain entropy: %s",
396*00b67f09SDavid van Moolenbroek isc_result_totext(result));
397*00b67f09SDavid van Moolenbroek goto failure;
398*00b67f09SDavid van Moolenbroek }
399*00b67f09SDavid van Moolenbroek
400*00b67f09SDavid van Moolenbroek r.base = randomdata;
401*00b67f09SDavid van Moolenbroek r.length = TKEY_RANDOM_AMOUNT;
402*00b67f09SDavid van Moolenbroek r2.base = tkeyin->key;
403*00b67f09SDavid van Moolenbroek r2.length = tkeyin->keylen;
404*00b67f09SDavid van Moolenbroek RETERR(compute_secret(shared, &r2, &r, &secret));
405*00b67f09SDavid van Moolenbroek isc_buffer_free(&shared);
406*00b67f09SDavid van Moolenbroek
407*00b67f09SDavid van Moolenbroek RETERR(dns_tsigkey_create(name, &tkeyin->algorithm,
408*00b67f09SDavid van Moolenbroek isc_buffer_base(&secret),
409*00b67f09SDavid van Moolenbroek isc_buffer_usedlength(&secret),
410*00b67f09SDavid van Moolenbroek ISC_TRUE, signer, tkeyin->inception,
411*00b67f09SDavid van Moolenbroek tkeyin->expire, ring->mctx, ring, NULL));
412*00b67f09SDavid van Moolenbroek
413*00b67f09SDavid van Moolenbroek /* This key is good for a long time */
414*00b67f09SDavid van Moolenbroek tkeyout->inception = tkeyin->inception;
415*00b67f09SDavid van Moolenbroek tkeyout->expire = tkeyin->expire;
416*00b67f09SDavid van Moolenbroek
417*00b67f09SDavid van Moolenbroek tkeyout->key = randomdata;
418*00b67f09SDavid van Moolenbroek tkeyout->keylen = TKEY_RANDOM_AMOUNT;
419*00b67f09SDavid van Moolenbroek
420*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
421*00b67f09SDavid van Moolenbroek
422*00b67f09SDavid van Moolenbroek failure:
423*00b67f09SDavid van Moolenbroek if (!ISC_LIST_EMPTY(*namelist))
424*00b67f09SDavid van Moolenbroek free_namelist(msg, namelist);
425*00b67f09SDavid van Moolenbroek if (shared != NULL)
426*00b67f09SDavid van Moolenbroek isc_buffer_free(&shared);
427*00b67f09SDavid van Moolenbroek if (pubkey != NULL)
428*00b67f09SDavid van Moolenbroek dst_key_free(&pubkey);
429*00b67f09SDavid van Moolenbroek if (randomdata != NULL)
430*00b67f09SDavid van Moolenbroek isc_mem_put(tkeyout->mctx, randomdata, TKEY_RANDOM_AMOUNT);
431*00b67f09SDavid van Moolenbroek return (result);
432*00b67f09SDavid van Moolenbroek }
433*00b67f09SDavid van Moolenbroek
434*00b67f09SDavid van Moolenbroek static isc_result_t
process_gsstkey(dns_name_t * name,dns_rdata_tkey_t * tkeyin,dns_tkeyctx_t * tctx,dns_rdata_tkey_t * tkeyout,dns_tsig_keyring_t * ring)435*00b67f09SDavid van Moolenbroek process_gsstkey(dns_name_t *name, dns_rdata_tkey_t *tkeyin,
436*00b67f09SDavid van Moolenbroek dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout,
437*00b67f09SDavid van Moolenbroek dns_tsig_keyring_t *ring)
438*00b67f09SDavid van Moolenbroek {
439*00b67f09SDavid van Moolenbroek isc_result_t result = ISC_R_SUCCESS;
440*00b67f09SDavid van Moolenbroek dst_key_t *dstkey = NULL;
441*00b67f09SDavid van Moolenbroek dns_tsigkey_t *tsigkey = NULL;
442*00b67f09SDavid van Moolenbroek dns_fixedname_t principal;
443*00b67f09SDavid van Moolenbroek isc_stdtime_t now;
444*00b67f09SDavid van Moolenbroek isc_region_t intoken;
445*00b67f09SDavid van Moolenbroek isc_buffer_t *outtoken = NULL;
446*00b67f09SDavid van Moolenbroek gss_ctx_id_t gss_ctx = NULL;
447*00b67f09SDavid van Moolenbroek
448*00b67f09SDavid van Moolenbroek /*
449*00b67f09SDavid van Moolenbroek * You have to define either a gss credential (principal) to
450*00b67f09SDavid van Moolenbroek * accept with tkey-gssapi-credential, or you have to
451*00b67f09SDavid van Moolenbroek * configure a specific keytab (with tkey-gssapi-keytab) in
452*00b67f09SDavid van Moolenbroek * order to use gsstkey
453*00b67f09SDavid van Moolenbroek */
454*00b67f09SDavid van Moolenbroek if (tctx->gsscred == NULL && tctx->gssapi_keytab == NULL) {
455*00b67f09SDavid van Moolenbroek tkey_log("process_gsstkey(): no tkey-gssapi-credential "
456*00b67f09SDavid van Moolenbroek "or tkey-gssapi-keytab configured");
457*00b67f09SDavid van Moolenbroek return (ISC_R_NOPERM);
458*00b67f09SDavid van Moolenbroek }
459*00b67f09SDavid van Moolenbroek
460*00b67f09SDavid van Moolenbroek if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) &&
461*00b67f09SDavid van Moolenbroek !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
462*00b67f09SDavid van Moolenbroek tkeyout->error = dns_tsigerror_badalg;
463*00b67f09SDavid van Moolenbroek tkey_log("process_gsstkey(): dns_tsigerror_badalg"); /* XXXSRA */
464*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
465*00b67f09SDavid van Moolenbroek }
466*00b67f09SDavid van Moolenbroek
467*00b67f09SDavid van Moolenbroek /*
468*00b67f09SDavid van Moolenbroek * XXXDCL need to check for key expiry per 4.1.1
469*00b67f09SDavid van Moolenbroek * XXXDCL need a way to check fully established, perhaps w/key_flags
470*00b67f09SDavid van Moolenbroek */
471*00b67f09SDavid van Moolenbroek
472*00b67f09SDavid van Moolenbroek intoken.base = tkeyin->key;
473*00b67f09SDavid van Moolenbroek intoken.length = tkeyin->keylen;
474*00b67f09SDavid van Moolenbroek
475*00b67f09SDavid van Moolenbroek result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
476*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
477*00b67f09SDavid van Moolenbroek gss_ctx = dst_key_getgssctx(tsigkey->key);
478*00b67f09SDavid van Moolenbroek
479*00b67f09SDavid van Moolenbroek dns_fixedname_init(&principal);
480*00b67f09SDavid van Moolenbroek
481*00b67f09SDavid van Moolenbroek /*
482*00b67f09SDavid van Moolenbroek * Note that tctx->gsscred may be NULL if tctx->gssapi_keytab is set
483*00b67f09SDavid van Moolenbroek */
484*00b67f09SDavid van Moolenbroek result = dst_gssapi_acceptctx(tctx->gsscred, tctx->gssapi_keytab,
485*00b67f09SDavid van Moolenbroek &intoken,
486*00b67f09SDavid van Moolenbroek &outtoken, &gss_ctx,
487*00b67f09SDavid van Moolenbroek dns_fixedname_name(&principal),
488*00b67f09SDavid van Moolenbroek tctx->mctx);
489*00b67f09SDavid van Moolenbroek if (result == DNS_R_INVALIDTKEY) {
490*00b67f09SDavid van Moolenbroek if (tsigkey != NULL)
491*00b67f09SDavid van Moolenbroek dns_tsigkey_detach(&tsigkey);
492*00b67f09SDavid van Moolenbroek tkeyout->error = dns_tsigerror_badkey;
493*00b67f09SDavid van Moolenbroek tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */
494*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
495*00b67f09SDavid van Moolenbroek }
496*00b67f09SDavid van Moolenbroek if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
497*00b67f09SDavid van Moolenbroek goto failure;
498*00b67f09SDavid van Moolenbroek /*
499*00b67f09SDavid van Moolenbroek * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
500*00b67f09SDavid van Moolenbroek */
501*00b67f09SDavid van Moolenbroek
502*00b67f09SDavid van Moolenbroek isc_stdtime_get(&now);
503*00b67f09SDavid van Moolenbroek
504*00b67f09SDavid van Moolenbroek if (tsigkey == NULL) {
505*00b67f09SDavid van Moolenbroek #ifdef GSSAPI
506*00b67f09SDavid van Moolenbroek OM_uint32 gret, minor, lifetime;
507*00b67f09SDavid van Moolenbroek #endif
508*00b67f09SDavid van Moolenbroek isc_uint32_t expire;
509*00b67f09SDavid van Moolenbroek
510*00b67f09SDavid van Moolenbroek RETERR(dst_key_fromgssapi(name, gss_ctx, ring->mctx,
511*00b67f09SDavid van Moolenbroek &dstkey, &intoken));
512*00b67f09SDavid van Moolenbroek /*
513*00b67f09SDavid van Moolenbroek * Limit keys to 1 hour or the context's lifetime whichever
514*00b67f09SDavid van Moolenbroek * is smaller.
515*00b67f09SDavid van Moolenbroek */
516*00b67f09SDavid van Moolenbroek expire = now + 3600;
517*00b67f09SDavid van Moolenbroek #ifdef GSSAPI
518*00b67f09SDavid van Moolenbroek gret = gss_context_time(&minor, gss_ctx, &lifetime);
519*00b67f09SDavid van Moolenbroek if (gret == GSS_S_COMPLETE && now + lifetime < expire)
520*00b67f09SDavid van Moolenbroek expire = now + lifetime;
521*00b67f09SDavid van Moolenbroek #endif
522*00b67f09SDavid van Moolenbroek RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
523*00b67f09SDavid van Moolenbroek dstkey, ISC_TRUE,
524*00b67f09SDavid van Moolenbroek dns_fixedname_name(&principal),
525*00b67f09SDavid van Moolenbroek now, expire, ring->mctx, ring,
526*00b67f09SDavid van Moolenbroek NULL));
527*00b67f09SDavid van Moolenbroek dst_key_free(&dstkey);
528*00b67f09SDavid van Moolenbroek tkeyout->inception = now;
529*00b67f09SDavid van Moolenbroek tkeyout->expire = expire;
530*00b67f09SDavid van Moolenbroek } else {
531*00b67f09SDavid van Moolenbroek tkeyout->inception = tsigkey->inception;
532*00b67f09SDavid van Moolenbroek tkeyout->expire = tsigkey->expire;
533*00b67f09SDavid van Moolenbroek dns_tsigkey_detach(&tsigkey);
534*00b67f09SDavid van Moolenbroek }
535*00b67f09SDavid van Moolenbroek
536*00b67f09SDavid van Moolenbroek if (outtoken) {
537*00b67f09SDavid van Moolenbroek tkeyout->key = isc_mem_get(tkeyout->mctx,
538*00b67f09SDavid van Moolenbroek isc_buffer_usedlength(outtoken));
539*00b67f09SDavid van Moolenbroek if (tkeyout->key == NULL) {
540*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
541*00b67f09SDavid van Moolenbroek goto failure;
542*00b67f09SDavid van Moolenbroek }
543*00b67f09SDavid van Moolenbroek tkeyout->keylen = isc_buffer_usedlength(outtoken);
544*00b67f09SDavid van Moolenbroek memmove(tkeyout->key, isc_buffer_base(outtoken),
545*00b67f09SDavid van Moolenbroek isc_buffer_usedlength(outtoken));
546*00b67f09SDavid van Moolenbroek isc_buffer_free(&outtoken);
547*00b67f09SDavid van Moolenbroek } else {
548*00b67f09SDavid van Moolenbroek tkeyout->key = isc_mem_get(tkeyout->mctx, tkeyin->keylen);
549*00b67f09SDavid van Moolenbroek if (tkeyout->key == NULL) {
550*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
551*00b67f09SDavid van Moolenbroek goto failure;
552*00b67f09SDavid van Moolenbroek }
553*00b67f09SDavid van Moolenbroek tkeyout->keylen = tkeyin->keylen;
554*00b67f09SDavid van Moolenbroek memmove(tkeyout->key, tkeyin->key, tkeyin->keylen);
555*00b67f09SDavid van Moolenbroek }
556*00b67f09SDavid van Moolenbroek
557*00b67f09SDavid van Moolenbroek tkeyout->error = dns_rcode_noerror;
558*00b67f09SDavid van Moolenbroek
559*00b67f09SDavid van Moolenbroek tkey_log("process_gsstkey(): dns_tsigerror_noerror"); /* XXXSRA */
560*00b67f09SDavid van Moolenbroek
561*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
562*00b67f09SDavid van Moolenbroek
563*00b67f09SDavid van Moolenbroek failure:
564*00b67f09SDavid van Moolenbroek if (tsigkey != NULL)
565*00b67f09SDavid van Moolenbroek dns_tsigkey_detach(&tsigkey);
566*00b67f09SDavid van Moolenbroek
567*00b67f09SDavid van Moolenbroek if (dstkey != NULL)
568*00b67f09SDavid van Moolenbroek dst_key_free(&dstkey);
569*00b67f09SDavid van Moolenbroek
570*00b67f09SDavid van Moolenbroek if (outtoken != NULL)
571*00b67f09SDavid van Moolenbroek isc_buffer_free(&outtoken);
572*00b67f09SDavid van Moolenbroek
573*00b67f09SDavid van Moolenbroek tkey_log("process_gsstkey(): %s",
574*00b67f09SDavid van Moolenbroek isc_result_totext(result)); /* XXXSRA */
575*00b67f09SDavid van Moolenbroek
576*00b67f09SDavid van Moolenbroek return (result);
577*00b67f09SDavid van Moolenbroek }
578*00b67f09SDavid van Moolenbroek
579*00b67f09SDavid van Moolenbroek static isc_result_t
process_deletetkey(dns_name_t * signer,dns_name_t * name,dns_rdata_tkey_t * tkeyin,dns_rdata_tkey_t * tkeyout,dns_tsig_keyring_t * ring)580*00b67f09SDavid van Moolenbroek process_deletetkey(dns_name_t *signer, dns_name_t *name,
581*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t *tkeyin, dns_rdata_tkey_t *tkeyout,
582*00b67f09SDavid van Moolenbroek dns_tsig_keyring_t *ring)
583*00b67f09SDavid van Moolenbroek {
584*00b67f09SDavid van Moolenbroek isc_result_t result;
585*00b67f09SDavid van Moolenbroek dns_tsigkey_t *tsigkey = NULL;
586*00b67f09SDavid van Moolenbroek dns_name_t *identity;
587*00b67f09SDavid van Moolenbroek
588*00b67f09SDavid van Moolenbroek result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
589*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
590*00b67f09SDavid van Moolenbroek tkeyout->error = dns_tsigerror_badname;
591*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
592*00b67f09SDavid van Moolenbroek }
593*00b67f09SDavid van Moolenbroek
594*00b67f09SDavid van Moolenbroek /*
595*00b67f09SDavid van Moolenbroek * Only allow a delete if the identity that created the key is the
596*00b67f09SDavid van Moolenbroek * same as the identity that signed the message.
597*00b67f09SDavid van Moolenbroek */
598*00b67f09SDavid van Moolenbroek identity = dns_tsigkey_identity(tsigkey);
599*00b67f09SDavid van Moolenbroek if (identity == NULL || !dns_name_equal(identity, signer)) {
600*00b67f09SDavid van Moolenbroek dns_tsigkey_detach(&tsigkey);
601*00b67f09SDavid van Moolenbroek return (DNS_R_REFUSED);
602*00b67f09SDavid van Moolenbroek }
603*00b67f09SDavid van Moolenbroek
604*00b67f09SDavid van Moolenbroek /*
605*00b67f09SDavid van Moolenbroek * Set the key to be deleted when no references are left. If the key
606*00b67f09SDavid van Moolenbroek * was not generated with TKEY and is in the config file, it may be
607*00b67f09SDavid van Moolenbroek * reloaded later.
608*00b67f09SDavid van Moolenbroek */
609*00b67f09SDavid van Moolenbroek dns_tsigkey_setdeleted(tsigkey);
610*00b67f09SDavid van Moolenbroek
611*00b67f09SDavid van Moolenbroek /* Release the reference */
612*00b67f09SDavid van Moolenbroek dns_tsigkey_detach(&tsigkey);
613*00b67f09SDavid van Moolenbroek
614*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
615*00b67f09SDavid van Moolenbroek }
616*00b67f09SDavid van Moolenbroek
617*00b67f09SDavid van Moolenbroek isc_result_t
dns_tkey_processquery(dns_message_t * msg,dns_tkeyctx_t * tctx,dns_tsig_keyring_t * ring)618*00b67f09SDavid van Moolenbroek dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
619*00b67f09SDavid van Moolenbroek dns_tsig_keyring_t *ring)
620*00b67f09SDavid van Moolenbroek {
621*00b67f09SDavid van Moolenbroek isc_result_t result = ISC_R_SUCCESS;
622*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t tkeyin, tkeyout;
623*00b67f09SDavid van Moolenbroek isc_boolean_t freetkeyin = ISC_FALSE;
624*00b67f09SDavid van Moolenbroek dns_name_t *qname, *name, *keyname, *signer, tsigner;
625*00b67f09SDavid van Moolenbroek dns_fixedname_t fkeyname;
626*00b67f09SDavid van Moolenbroek dns_rdataset_t *tkeyset;
627*00b67f09SDavid van Moolenbroek dns_rdata_t rdata;
628*00b67f09SDavid van Moolenbroek dns_namelist_t namelist;
629*00b67f09SDavid van Moolenbroek char tkeyoutdata[512];
630*00b67f09SDavid van Moolenbroek isc_buffer_t tkeyoutbuf;
631*00b67f09SDavid van Moolenbroek
632*00b67f09SDavid van Moolenbroek REQUIRE(msg != NULL);
633*00b67f09SDavid van Moolenbroek REQUIRE(tctx != NULL);
634*00b67f09SDavid van Moolenbroek REQUIRE(ring != NULL);
635*00b67f09SDavid van Moolenbroek
636*00b67f09SDavid van Moolenbroek ISC_LIST_INIT(namelist);
637*00b67f09SDavid van Moolenbroek
638*00b67f09SDavid van Moolenbroek /*
639*00b67f09SDavid van Moolenbroek * Interpret the question section.
640*00b67f09SDavid van Moolenbroek */
641*00b67f09SDavid van Moolenbroek result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
642*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
643*00b67f09SDavid van Moolenbroek return (DNS_R_FORMERR);
644*00b67f09SDavid van Moolenbroek
645*00b67f09SDavid van Moolenbroek qname = NULL;
646*00b67f09SDavid van Moolenbroek dns_message_currentname(msg, DNS_SECTION_QUESTION, &qname);
647*00b67f09SDavid van Moolenbroek
648*00b67f09SDavid van Moolenbroek /*
649*00b67f09SDavid van Moolenbroek * Look for a TKEY record that matches the question.
650*00b67f09SDavid van Moolenbroek */
651*00b67f09SDavid van Moolenbroek tkeyset = NULL;
652*00b67f09SDavid van Moolenbroek name = NULL;
653*00b67f09SDavid van Moolenbroek result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL, qname,
654*00b67f09SDavid van Moolenbroek dns_rdatatype_tkey, 0, &name, &tkeyset);
655*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
656*00b67f09SDavid van Moolenbroek /*
657*00b67f09SDavid van Moolenbroek * Try the answer section, since that's where Win2000
658*00b67f09SDavid van Moolenbroek * puts it.
659*00b67f09SDavid van Moolenbroek */
660*00b67f09SDavid van Moolenbroek name = NULL;
661*00b67f09SDavid van Moolenbroek if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
662*00b67f09SDavid van Moolenbroek dns_rdatatype_tkey, 0, &name,
663*00b67f09SDavid van Moolenbroek &tkeyset) != ISC_R_SUCCESS) {
664*00b67f09SDavid van Moolenbroek result = DNS_R_FORMERR;
665*00b67f09SDavid van Moolenbroek tkey_log("dns_tkey_processquery: couldn't find a TKEY "
666*00b67f09SDavid van Moolenbroek "matching the question");
667*00b67f09SDavid van Moolenbroek goto failure;
668*00b67f09SDavid van Moolenbroek }
669*00b67f09SDavid van Moolenbroek }
670*00b67f09SDavid van Moolenbroek result = dns_rdataset_first(tkeyset);
671*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
672*00b67f09SDavid van Moolenbroek result = DNS_R_FORMERR;
673*00b67f09SDavid van Moolenbroek goto failure;
674*00b67f09SDavid van Moolenbroek }
675*00b67f09SDavid van Moolenbroek dns_rdata_init(&rdata);
676*00b67f09SDavid van Moolenbroek dns_rdataset_current(tkeyset, &rdata);
677*00b67f09SDavid van Moolenbroek
678*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_tostruct(&rdata, &tkeyin, NULL));
679*00b67f09SDavid van Moolenbroek freetkeyin = ISC_TRUE;
680*00b67f09SDavid van Moolenbroek
681*00b67f09SDavid van Moolenbroek if (tkeyin.error != dns_rcode_noerror) {
682*00b67f09SDavid van Moolenbroek result = DNS_R_FORMERR;
683*00b67f09SDavid van Moolenbroek goto failure;
684*00b67f09SDavid van Moolenbroek }
685*00b67f09SDavid van Moolenbroek
686*00b67f09SDavid van Moolenbroek /*
687*00b67f09SDavid van Moolenbroek * Before we go any farther, verify that the message was signed.
688*00b67f09SDavid van Moolenbroek * GSSAPI TKEY doesn't require a signature, the rest do.
689*00b67f09SDavid van Moolenbroek */
690*00b67f09SDavid van Moolenbroek dns_name_init(&tsigner, NULL);
691*00b67f09SDavid van Moolenbroek result = dns_message_signer(msg, &tsigner);
692*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS) {
693*00b67f09SDavid van Moolenbroek if (tkeyin.mode == DNS_TKEYMODE_GSSAPI &&
694*00b67f09SDavid van Moolenbroek result == ISC_R_NOTFOUND)
695*00b67f09SDavid van Moolenbroek signer = NULL;
696*00b67f09SDavid van Moolenbroek else {
697*00b67f09SDavid van Moolenbroek tkey_log("dns_tkey_processquery: query was not "
698*00b67f09SDavid van Moolenbroek "properly signed - rejecting");
699*00b67f09SDavid van Moolenbroek result = DNS_R_FORMERR;
700*00b67f09SDavid van Moolenbroek goto failure;
701*00b67f09SDavid van Moolenbroek }
702*00b67f09SDavid van Moolenbroek } else
703*00b67f09SDavid van Moolenbroek signer = &tsigner;
704*00b67f09SDavid van Moolenbroek
705*00b67f09SDavid van Moolenbroek tkeyout.common.rdclass = tkeyin.common.rdclass;
706*00b67f09SDavid van Moolenbroek tkeyout.common.rdtype = tkeyin.common.rdtype;
707*00b67f09SDavid van Moolenbroek ISC_LINK_INIT(&tkeyout.common, link);
708*00b67f09SDavid van Moolenbroek tkeyout.mctx = msg->mctx;
709*00b67f09SDavid van Moolenbroek
710*00b67f09SDavid van Moolenbroek dns_name_init(&tkeyout.algorithm, NULL);
711*00b67f09SDavid van Moolenbroek dns_name_clone(&tkeyin.algorithm, &tkeyout.algorithm);
712*00b67f09SDavid van Moolenbroek
713*00b67f09SDavid van Moolenbroek tkeyout.inception = tkeyout.expire = 0;
714*00b67f09SDavid van Moolenbroek tkeyout.mode = tkeyin.mode;
715*00b67f09SDavid van Moolenbroek tkeyout.error = 0;
716*00b67f09SDavid van Moolenbroek tkeyout.keylen = tkeyout.otherlen = 0;
717*00b67f09SDavid van Moolenbroek tkeyout.key = tkeyout.other = NULL;
718*00b67f09SDavid van Moolenbroek
719*00b67f09SDavid van Moolenbroek /*
720*00b67f09SDavid van Moolenbroek * A delete operation must have a fully specified key name. If this
721*00b67f09SDavid van Moolenbroek * is not a delete, we do the following:
722*00b67f09SDavid van Moolenbroek * if (qname != ".")
723*00b67f09SDavid van Moolenbroek * keyname = qname + defaultdomain
724*00b67f09SDavid van Moolenbroek * else
725*00b67f09SDavid van Moolenbroek * keyname = <random hex> + defaultdomain
726*00b67f09SDavid van Moolenbroek */
727*00b67f09SDavid van Moolenbroek if (tkeyin.mode != DNS_TKEYMODE_DELETE) {
728*00b67f09SDavid van Moolenbroek dns_tsigkey_t *tsigkey = NULL;
729*00b67f09SDavid van Moolenbroek
730*00b67f09SDavid van Moolenbroek if (tctx->domain == NULL && tkeyin.mode != DNS_TKEYMODE_GSSAPI) {
731*00b67f09SDavid van Moolenbroek tkey_log("dns_tkey_processquery: tkey-domain not set");
732*00b67f09SDavid van Moolenbroek result = DNS_R_REFUSED;
733*00b67f09SDavid van Moolenbroek goto failure;
734*00b67f09SDavid van Moolenbroek }
735*00b67f09SDavid van Moolenbroek
736*00b67f09SDavid van Moolenbroek dns_fixedname_init(&fkeyname);
737*00b67f09SDavid van Moolenbroek keyname = dns_fixedname_name(&fkeyname);
738*00b67f09SDavid van Moolenbroek
739*00b67f09SDavid van Moolenbroek if (!dns_name_equal(qname, dns_rootname)) {
740*00b67f09SDavid van Moolenbroek unsigned int n = dns_name_countlabels(qname);
741*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(dns_name_copy(qname, keyname, NULL)
742*00b67f09SDavid van Moolenbroek == ISC_R_SUCCESS);
743*00b67f09SDavid van Moolenbroek dns_name_getlabelsequence(keyname, 0, n - 1, keyname);
744*00b67f09SDavid van Moolenbroek } else {
745*00b67f09SDavid van Moolenbroek static char hexdigits[16] = {
746*00b67f09SDavid van Moolenbroek '0', '1', '2', '3', '4', '5', '6', '7',
747*00b67f09SDavid van Moolenbroek '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
748*00b67f09SDavid van Moolenbroek unsigned char randomdata[16];
749*00b67f09SDavid van Moolenbroek char randomtext[32];
750*00b67f09SDavid van Moolenbroek isc_buffer_t b;
751*00b67f09SDavid van Moolenbroek unsigned int i, j;
752*00b67f09SDavid van Moolenbroek
753*00b67f09SDavid van Moolenbroek result = isc_entropy_getdata(tctx->ectx,
754*00b67f09SDavid van Moolenbroek randomdata,
755*00b67f09SDavid van Moolenbroek sizeof(randomdata),
756*00b67f09SDavid van Moolenbroek NULL, 0);
757*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
758*00b67f09SDavid van Moolenbroek goto failure;
759*00b67f09SDavid van Moolenbroek
760*00b67f09SDavid van Moolenbroek for (i = 0, j = 0; i < sizeof(randomdata); i++) {
761*00b67f09SDavid van Moolenbroek unsigned char val = randomdata[i];
762*00b67f09SDavid van Moolenbroek randomtext[j++] = hexdigits[val >> 4];
763*00b67f09SDavid van Moolenbroek randomtext[j++] = hexdigits[val & 0xF];
764*00b67f09SDavid van Moolenbroek }
765*00b67f09SDavid van Moolenbroek isc_buffer_init(&b, randomtext, sizeof(randomtext));
766*00b67f09SDavid van Moolenbroek isc_buffer_add(&b, sizeof(randomtext));
767*00b67f09SDavid van Moolenbroek result = dns_name_fromtext(keyname, &b, NULL, 0, NULL);
768*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
769*00b67f09SDavid van Moolenbroek goto failure;
770*00b67f09SDavid van Moolenbroek }
771*00b67f09SDavid van Moolenbroek
772*00b67f09SDavid van Moolenbroek if (tkeyin.mode == DNS_TKEYMODE_GSSAPI) {
773*00b67f09SDavid van Moolenbroek /* Yup. This is a hack */
774*00b67f09SDavid van Moolenbroek result = dns_name_concatenate(keyname, dns_rootname,
775*00b67f09SDavid van Moolenbroek keyname, NULL);
776*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
777*00b67f09SDavid van Moolenbroek goto failure;
778*00b67f09SDavid van Moolenbroek } else {
779*00b67f09SDavid van Moolenbroek result = dns_name_concatenate(keyname, tctx->domain,
780*00b67f09SDavid van Moolenbroek keyname, NULL);
781*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
782*00b67f09SDavid van Moolenbroek goto failure;
783*00b67f09SDavid van Moolenbroek }
784*00b67f09SDavid van Moolenbroek
785*00b67f09SDavid van Moolenbroek result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring);
786*00b67f09SDavid van Moolenbroek
787*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS) {
788*00b67f09SDavid van Moolenbroek tkeyout.error = dns_tsigerror_badname;
789*00b67f09SDavid van Moolenbroek dns_tsigkey_detach(&tsigkey);
790*00b67f09SDavid van Moolenbroek goto failure_with_tkey;
791*00b67f09SDavid van Moolenbroek } else if (result != ISC_R_NOTFOUND)
792*00b67f09SDavid van Moolenbroek goto failure;
793*00b67f09SDavid van Moolenbroek } else
794*00b67f09SDavid van Moolenbroek keyname = qname;
795*00b67f09SDavid van Moolenbroek
796*00b67f09SDavid van Moolenbroek switch (tkeyin.mode) {
797*00b67f09SDavid van Moolenbroek case DNS_TKEYMODE_DIFFIEHELLMAN:
798*00b67f09SDavid van Moolenbroek tkeyout.error = dns_rcode_noerror;
799*00b67f09SDavid van Moolenbroek RETERR(process_dhtkey(msg, signer, keyname, &tkeyin,
800*00b67f09SDavid van Moolenbroek tctx, &tkeyout, ring,
801*00b67f09SDavid van Moolenbroek &namelist));
802*00b67f09SDavid van Moolenbroek break;
803*00b67f09SDavid van Moolenbroek case DNS_TKEYMODE_GSSAPI:
804*00b67f09SDavid van Moolenbroek tkeyout.error = dns_rcode_noerror;
805*00b67f09SDavid van Moolenbroek RETERR(process_gsstkey(keyname, &tkeyin, tctx,
806*00b67f09SDavid van Moolenbroek &tkeyout, ring));
807*00b67f09SDavid van Moolenbroek break;
808*00b67f09SDavid van Moolenbroek case DNS_TKEYMODE_DELETE:
809*00b67f09SDavid van Moolenbroek tkeyout.error = dns_rcode_noerror;
810*00b67f09SDavid van Moolenbroek RETERR(process_deletetkey(signer, keyname, &tkeyin,
811*00b67f09SDavid van Moolenbroek &tkeyout, ring));
812*00b67f09SDavid van Moolenbroek break;
813*00b67f09SDavid van Moolenbroek case DNS_TKEYMODE_SERVERASSIGNED:
814*00b67f09SDavid van Moolenbroek case DNS_TKEYMODE_RESOLVERASSIGNED:
815*00b67f09SDavid van Moolenbroek result = DNS_R_NOTIMP;
816*00b67f09SDavid van Moolenbroek goto failure;
817*00b67f09SDavid van Moolenbroek default:
818*00b67f09SDavid van Moolenbroek tkeyout.error = dns_tsigerror_badmode;
819*00b67f09SDavid van Moolenbroek }
820*00b67f09SDavid van Moolenbroek
821*00b67f09SDavid van Moolenbroek failure_with_tkey:
822*00b67f09SDavid van Moolenbroek dns_rdata_init(&rdata);
823*00b67f09SDavid van Moolenbroek isc_buffer_init(&tkeyoutbuf, tkeyoutdata, sizeof(tkeyoutdata));
824*00b67f09SDavid van Moolenbroek result = dns_rdata_fromstruct(&rdata, tkeyout.common.rdclass,
825*00b67f09SDavid van Moolenbroek tkeyout.common.rdtype, &tkeyout,
826*00b67f09SDavid van Moolenbroek &tkeyoutbuf);
827*00b67f09SDavid van Moolenbroek
828*00b67f09SDavid van Moolenbroek if (freetkeyin) {
829*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&tkeyin);
830*00b67f09SDavid van Moolenbroek freetkeyin = ISC_FALSE;
831*00b67f09SDavid van Moolenbroek }
832*00b67f09SDavid van Moolenbroek
833*00b67f09SDavid van Moolenbroek if (tkeyout.key != NULL)
834*00b67f09SDavid van Moolenbroek isc_mem_put(tkeyout.mctx, tkeyout.key, tkeyout.keylen);
835*00b67f09SDavid van Moolenbroek if (tkeyout.other != NULL)
836*00b67f09SDavid van Moolenbroek isc_mem_put(tkeyout.mctx, tkeyout.other, tkeyout.otherlen);
837*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
838*00b67f09SDavid van Moolenbroek goto failure;
839*00b67f09SDavid van Moolenbroek
840*00b67f09SDavid van Moolenbroek RETERR(add_rdata_to_list(msg, keyname, &rdata, 0, &namelist));
841*00b67f09SDavid van Moolenbroek
842*00b67f09SDavid van Moolenbroek RETERR(dns_message_reply(msg, ISC_TRUE));
843*00b67f09SDavid van Moolenbroek
844*00b67f09SDavid van Moolenbroek name = ISC_LIST_HEAD(namelist);
845*00b67f09SDavid van Moolenbroek while (name != NULL) {
846*00b67f09SDavid van Moolenbroek dns_name_t *next = ISC_LIST_NEXT(name, link);
847*00b67f09SDavid van Moolenbroek ISC_LIST_UNLINK(namelist, name, link);
848*00b67f09SDavid van Moolenbroek dns_message_addname(msg, name, DNS_SECTION_ANSWER);
849*00b67f09SDavid van Moolenbroek name = next;
850*00b67f09SDavid van Moolenbroek }
851*00b67f09SDavid van Moolenbroek
852*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
853*00b67f09SDavid van Moolenbroek
854*00b67f09SDavid van Moolenbroek failure:
855*00b67f09SDavid van Moolenbroek if (freetkeyin)
856*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&tkeyin);
857*00b67f09SDavid van Moolenbroek if (!ISC_LIST_EMPTY(namelist))
858*00b67f09SDavid van Moolenbroek free_namelist(msg, &namelist);
859*00b67f09SDavid van Moolenbroek return (result);
860*00b67f09SDavid van Moolenbroek }
861*00b67f09SDavid van Moolenbroek
862*00b67f09SDavid van Moolenbroek static isc_result_t
buildquery(dns_message_t * msg,dns_name_t * name,dns_rdata_tkey_t * tkey,isc_boolean_t win2k)863*00b67f09SDavid van Moolenbroek buildquery(dns_message_t *msg, dns_name_t *name,
864*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t *tkey, isc_boolean_t win2k)
865*00b67f09SDavid van Moolenbroek {
866*00b67f09SDavid van Moolenbroek dns_name_t *qname = NULL, *aname = NULL;
867*00b67f09SDavid van Moolenbroek dns_rdataset_t *question = NULL, *tkeyset = NULL;
868*00b67f09SDavid van Moolenbroek dns_rdatalist_t *tkeylist = NULL;
869*00b67f09SDavid van Moolenbroek dns_rdata_t *rdata = NULL;
870*00b67f09SDavid van Moolenbroek isc_buffer_t *dynbuf = NULL, *anamebuf = NULL, *qnamebuf = NULL;
871*00b67f09SDavid van Moolenbroek isc_result_t result;
872*00b67f09SDavid van Moolenbroek
873*00b67f09SDavid van Moolenbroek REQUIRE(msg != NULL);
874*00b67f09SDavid van Moolenbroek REQUIRE(name != NULL);
875*00b67f09SDavid van Moolenbroek REQUIRE(tkey != NULL);
876*00b67f09SDavid van Moolenbroek
877*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettempname(msg, &qname));
878*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettempname(msg, &aname));
879*00b67f09SDavid van Moolenbroek
880*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettemprdataset(msg, &question));
881*00b67f09SDavid van Moolenbroek dns_rdataset_makequestion(question, dns_rdataclass_any,
882*00b67f09SDavid van Moolenbroek dns_rdatatype_tkey);
883*00b67f09SDavid van Moolenbroek
884*00b67f09SDavid van Moolenbroek RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 4096));
885*00b67f09SDavid van Moolenbroek RETERR(isc_buffer_allocate(msg->mctx, &anamebuf, DNS_NAME_MAXWIRE));
886*00b67f09SDavid van Moolenbroek RETERR(isc_buffer_allocate(msg->mctx, &qnamebuf, DNS_NAME_MAXWIRE));
887*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettemprdata(msg, &rdata));
888*00b67f09SDavid van Moolenbroek
889*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
890*00b67f09SDavid van Moolenbroek dns_rdatatype_tkey, tkey, dynbuf));
891*00b67f09SDavid van Moolenbroek dns_message_takebuffer(msg, &dynbuf);
892*00b67f09SDavid van Moolenbroek
893*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettemprdatalist(msg, &tkeylist));
894*00b67f09SDavid van Moolenbroek tkeylist->rdclass = dns_rdataclass_any;
895*00b67f09SDavid van Moolenbroek tkeylist->type = dns_rdatatype_tkey;
896*00b67f09SDavid van Moolenbroek tkeylist->covers = 0;
897*00b67f09SDavid van Moolenbroek tkeylist->ttl = 0;
898*00b67f09SDavid van Moolenbroek ISC_LIST_INIT(tkeylist->rdata);
899*00b67f09SDavid van Moolenbroek ISC_LIST_APPEND(tkeylist->rdata, rdata, link);
900*00b67f09SDavid van Moolenbroek
901*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettemprdataset(msg, &tkeyset));
902*00b67f09SDavid van Moolenbroek RETERR(dns_rdatalist_tordataset(tkeylist, tkeyset));
903*00b67f09SDavid van Moolenbroek
904*00b67f09SDavid van Moolenbroek dns_name_init(qname, NULL);
905*00b67f09SDavid van Moolenbroek dns_name_copy(name, qname, qnamebuf);
906*00b67f09SDavid van Moolenbroek
907*00b67f09SDavid van Moolenbroek dns_name_init(aname, NULL);
908*00b67f09SDavid van Moolenbroek dns_name_copy(name, aname, anamebuf);
909*00b67f09SDavid van Moolenbroek
910*00b67f09SDavid van Moolenbroek ISC_LIST_APPEND(qname->list, question, link);
911*00b67f09SDavid van Moolenbroek ISC_LIST_APPEND(aname->list, tkeyset, link);
912*00b67f09SDavid van Moolenbroek
913*00b67f09SDavid van Moolenbroek dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
914*00b67f09SDavid van Moolenbroek dns_message_takebuffer(msg, &qnamebuf);
915*00b67f09SDavid van Moolenbroek
916*00b67f09SDavid van Moolenbroek /*
917*00b67f09SDavid van Moolenbroek * Windows 2000 needs this in the answer section, not the additional
918*00b67f09SDavid van Moolenbroek * section where the RFC specifies.
919*00b67f09SDavid van Moolenbroek */
920*00b67f09SDavid van Moolenbroek if (win2k)
921*00b67f09SDavid van Moolenbroek dns_message_addname(msg, aname, DNS_SECTION_ANSWER);
922*00b67f09SDavid van Moolenbroek else
923*00b67f09SDavid van Moolenbroek dns_message_addname(msg, aname, DNS_SECTION_ADDITIONAL);
924*00b67f09SDavid van Moolenbroek dns_message_takebuffer(msg, &anamebuf);
925*00b67f09SDavid van Moolenbroek
926*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
927*00b67f09SDavid van Moolenbroek
928*00b67f09SDavid van Moolenbroek failure:
929*00b67f09SDavid van Moolenbroek if (qname != NULL)
930*00b67f09SDavid van Moolenbroek dns_message_puttempname(msg, &qname);
931*00b67f09SDavid van Moolenbroek if (aname != NULL)
932*00b67f09SDavid van Moolenbroek dns_message_puttempname(msg, &aname);
933*00b67f09SDavid van Moolenbroek if (question != NULL) {
934*00b67f09SDavid van Moolenbroek dns_rdataset_disassociate(question);
935*00b67f09SDavid van Moolenbroek dns_message_puttemprdataset(msg, &question);
936*00b67f09SDavid van Moolenbroek }
937*00b67f09SDavid van Moolenbroek if (dynbuf != NULL)
938*00b67f09SDavid van Moolenbroek isc_buffer_free(&dynbuf);
939*00b67f09SDavid van Moolenbroek if (qnamebuf != NULL)
940*00b67f09SDavid van Moolenbroek isc_buffer_free(&qnamebuf);
941*00b67f09SDavid van Moolenbroek if (anamebuf != NULL)
942*00b67f09SDavid van Moolenbroek isc_buffer_free(&anamebuf);
943*00b67f09SDavid van Moolenbroek printf("buildquery error\n");
944*00b67f09SDavid van Moolenbroek return (result);
945*00b67f09SDavid van Moolenbroek }
946*00b67f09SDavid van Moolenbroek
947*00b67f09SDavid van Moolenbroek isc_result_t
dns_tkey_builddhquery(dns_message_t * msg,dst_key_t * key,dns_name_t * name,dns_name_t * algorithm,isc_buffer_t * nonce,isc_uint32_t lifetime)948*00b67f09SDavid van Moolenbroek dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
949*00b67f09SDavid van Moolenbroek dns_name_t *algorithm, isc_buffer_t *nonce,
950*00b67f09SDavid van Moolenbroek isc_uint32_t lifetime)
951*00b67f09SDavid van Moolenbroek {
952*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t tkey;
953*00b67f09SDavid van Moolenbroek dns_rdata_t *rdata = NULL;
954*00b67f09SDavid van Moolenbroek isc_buffer_t *dynbuf = NULL;
955*00b67f09SDavid van Moolenbroek isc_region_t r;
956*00b67f09SDavid van Moolenbroek dns_name_t keyname;
957*00b67f09SDavid van Moolenbroek dns_namelist_t namelist;
958*00b67f09SDavid van Moolenbroek isc_result_t result;
959*00b67f09SDavid van Moolenbroek isc_stdtime_t now;
960*00b67f09SDavid van Moolenbroek
961*00b67f09SDavid van Moolenbroek REQUIRE(msg != NULL);
962*00b67f09SDavid van Moolenbroek REQUIRE(key != NULL);
963*00b67f09SDavid van Moolenbroek REQUIRE(dst_key_alg(key) == DNS_KEYALG_DH);
964*00b67f09SDavid van Moolenbroek REQUIRE(dst_key_isprivate(key));
965*00b67f09SDavid van Moolenbroek REQUIRE(name != NULL);
966*00b67f09SDavid van Moolenbroek REQUIRE(algorithm != NULL);
967*00b67f09SDavid van Moolenbroek
968*00b67f09SDavid van Moolenbroek tkey.common.rdclass = dns_rdataclass_any;
969*00b67f09SDavid van Moolenbroek tkey.common.rdtype = dns_rdatatype_tkey;
970*00b67f09SDavid van Moolenbroek ISC_LINK_INIT(&tkey.common, link);
971*00b67f09SDavid van Moolenbroek tkey.mctx = msg->mctx;
972*00b67f09SDavid van Moolenbroek dns_name_init(&tkey.algorithm, NULL);
973*00b67f09SDavid van Moolenbroek dns_name_clone(algorithm, &tkey.algorithm);
974*00b67f09SDavid van Moolenbroek isc_stdtime_get(&now);
975*00b67f09SDavid van Moolenbroek tkey.inception = now;
976*00b67f09SDavid van Moolenbroek tkey.expire = now + lifetime;
977*00b67f09SDavid van Moolenbroek tkey.mode = DNS_TKEYMODE_DIFFIEHELLMAN;
978*00b67f09SDavid van Moolenbroek if (nonce != NULL)
979*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(nonce, &r);
980*00b67f09SDavid van Moolenbroek else {
981*00b67f09SDavid van Moolenbroek r.base = isc_mem_get(msg->mctx, 0);
982*00b67f09SDavid van Moolenbroek r.length = 0;
983*00b67f09SDavid van Moolenbroek }
984*00b67f09SDavid van Moolenbroek tkey.error = 0;
985*00b67f09SDavid van Moolenbroek tkey.key = r.base;
986*00b67f09SDavid van Moolenbroek tkey.keylen = r.length;
987*00b67f09SDavid van Moolenbroek tkey.other = NULL;
988*00b67f09SDavid van Moolenbroek tkey.otherlen = 0;
989*00b67f09SDavid van Moolenbroek
990*00b67f09SDavid van Moolenbroek RETERR(buildquery(msg, name, &tkey, ISC_FALSE));
991*00b67f09SDavid van Moolenbroek
992*00b67f09SDavid van Moolenbroek if (nonce == NULL)
993*00b67f09SDavid van Moolenbroek isc_mem_put(msg->mctx, r.base, 0);
994*00b67f09SDavid van Moolenbroek
995*00b67f09SDavid van Moolenbroek RETERR(dns_message_gettemprdata(msg, &rdata));
996*00b67f09SDavid van Moolenbroek RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024));
997*00b67f09SDavid van Moolenbroek RETERR(dst_key_todns(key, dynbuf));
998*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(dynbuf, &r);
999*00b67f09SDavid van Moolenbroek dns_rdata_fromregion(rdata, dns_rdataclass_any,
1000*00b67f09SDavid van Moolenbroek dns_rdatatype_key, &r);
1001*00b67f09SDavid van Moolenbroek dns_message_takebuffer(msg, &dynbuf);
1002*00b67f09SDavid van Moolenbroek
1003*00b67f09SDavid van Moolenbroek dns_name_init(&keyname, NULL);
1004*00b67f09SDavid van Moolenbroek dns_name_clone(dst_key_name(key), &keyname);
1005*00b67f09SDavid van Moolenbroek
1006*00b67f09SDavid van Moolenbroek ISC_LIST_INIT(namelist);
1007*00b67f09SDavid van Moolenbroek RETERR(add_rdata_to_list(msg, &keyname, rdata, 0, &namelist));
1008*00b67f09SDavid van Moolenbroek name = ISC_LIST_HEAD(namelist);
1009*00b67f09SDavid van Moolenbroek while (name != NULL) {
1010*00b67f09SDavid van Moolenbroek dns_name_t *next = ISC_LIST_NEXT(name, link);
1011*00b67f09SDavid van Moolenbroek ISC_LIST_UNLINK(namelist, name, link);
1012*00b67f09SDavid van Moolenbroek dns_message_addname(msg, name, DNS_SECTION_ADDITIONAL);
1013*00b67f09SDavid van Moolenbroek name = next;
1014*00b67f09SDavid van Moolenbroek }
1015*00b67f09SDavid van Moolenbroek
1016*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1017*00b67f09SDavid van Moolenbroek
1018*00b67f09SDavid van Moolenbroek failure:
1019*00b67f09SDavid van Moolenbroek
1020*00b67f09SDavid van Moolenbroek if (dynbuf != NULL)
1021*00b67f09SDavid van Moolenbroek isc_buffer_free(&dynbuf);
1022*00b67f09SDavid van Moolenbroek return (result);
1023*00b67f09SDavid van Moolenbroek }
1024*00b67f09SDavid van Moolenbroek
1025*00b67f09SDavid van Moolenbroek isc_result_t
dns_tkey_buildgssquery(dns_message_t * msg,dns_name_t * name,dns_name_t * gname,isc_buffer_t * intoken,isc_uint32_t lifetime,gss_ctx_id_t * context,isc_boolean_t win2k,isc_mem_t * mctx,char ** err_message)1026*00b67f09SDavid van Moolenbroek dns_tkey_buildgssquery(dns_message_t *msg, dns_name_t *name, dns_name_t *gname,
1027*00b67f09SDavid van Moolenbroek isc_buffer_t *intoken, isc_uint32_t lifetime,
1028*00b67f09SDavid van Moolenbroek gss_ctx_id_t *context, isc_boolean_t win2k,
1029*00b67f09SDavid van Moolenbroek isc_mem_t *mctx, char **err_message)
1030*00b67f09SDavid van Moolenbroek {
1031*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t tkey;
1032*00b67f09SDavid van Moolenbroek isc_result_t result;
1033*00b67f09SDavid van Moolenbroek isc_stdtime_t now;
1034*00b67f09SDavid van Moolenbroek isc_buffer_t token;
1035*00b67f09SDavid van Moolenbroek unsigned char array[4096];
1036*00b67f09SDavid van Moolenbroek
1037*00b67f09SDavid van Moolenbroek UNUSED(intoken);
1038*00b67f09SDavid van Moolenbroek
1039*00b67f09SDavid van Moolenbroek REQUIRE(msg != NULL);
1040*00b67f09SDavid van Moolenbroek REQUIRE(name != NULL);
1041*00b67f09SDavid van Moolenbroek REQUIRE(gname != NULL);
1042*00b67f09SDavid van Moolenbroek REQUIRE(context != NULL);
1043*00b67f09SDavid van Moolenbroek REQUIRE(mctx != NULL);
1044*00b67f09SDavid van Moolenbroek
1045*00b67f09SDavid van Moolenbroek isc_buffer_init(&token, array, sizeof(array));
1046*00b67f09SDavid van Moolenbroek result = dst_gssapi_initctx(gname, NULL, &token, context,
1047*00b67f09SDavid van Moolenbroek mctx, err_message);
1048*00b67f09SDavid van Moolenbroek if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
1049*00b67f09SDavid van Moolenbroek return (result);
1050*00b67f09SDavid van Moolenbroek
1051*00b67f09SDavid van Moolenbroek tkey.common.rdclass = dns_rdataclass_any;
1052*00b67f09SDavid van Moolenbroek tkey.common.rdtype = dns_rdatatype_tkey;
1053*00b67f09SDavid van Moolenbroek ISC_LINK_INIT(&tkey.common, link);
1054*00b67f09SDavid van Moolenbroek tkey.mctx = NULL;
1055*00b67f09SDavid van Moolenbroek dns_name_init(&tkey.algorithm, NULL);
1056*00b67f09SDavid van Moolenbroek
1057*00b67f09SDavid van Moolenbroek if (win2k)
1058*00b67f09SDavid van Moolenbroek dns_name_clone(DNS_TSIG_GSSAPIMS_NAME, &tkey.algorithm);
1059*00b67f09SDavid van Moolenbroek else
1060*00b67f09SDavid van Moolenbroek dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
1061*00b67f09SDavid van Moolenbroek
1062*00b67f09SDavid van Moolenbroek isc_stdtime_get(&now);
1063*00b67f09SDavid van Moolenbroek tkey.inception = now;
1064*00b67f09SDavid van Moolenbroek tkey.expire = now + lifetime;
1065*00b67f09SDavid van Moolenbroek tkey.mode = DNS_TKEYMODE_GSSAPI;
1066*00b67f09SDavid van Moolenbroek tkey.error = 0;
1067*00b67f09SDavid van Moolenbroek tkey.key = isc_buffer_base(&token);
1068*00b67f09SDavid van Moolenbroek tkey.keylen = isc_buffer_usedlength(&token);
1069*00b67f09SDavid van Moolenbroek tkey.other = NULL;
1070*00b67f09SDavid van Moolenbroek tkey.otherlen = 0;
1071*00b67f09SDavid van Moolenbroek
1072*00b67f09SDavid van Moolenbroek RETERR(buildquery(msg, name, &tkey, win2k));
1073*00b67f09SDavid van Moolenbroek
1074*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1075*00b67f09SDavid van Moolenbroek
1076*00b67f09SDavid van Moolenbroek failure:
1077*00b67f09SDavid van Moolenbroek return (result);
1078*00b67f09SDavid van Moolenbroek }
1079*00b67f09SDavid van Moolenbroek
1080*00b67f09SDavid van Moolenbroek isc_result_t
dns_tkey_builddeletequery(dns_message_t * msg,dns_tsigkey_t * key)1081*00b67f09SDavid van Moolenbroek dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key) {
1082*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t tkey;
1083*00b67f09SDavid van Moolenbroek
1084*00b67f09SDavid van Moolenbroek REQUIRE(msg != NULL);
1085*00b67f09SDavid van Moolenbroek REQUIRE(key != NULL);
1086*00b67f09SDavid van Moolenbroek
1087*00b67f09SDavid van Moolenbroek tkey.common.rdclass = dns_rdataclass_any;
1088*00b67f09SDavid van Moolenbroek tkey.common.rdtype = dns_rdatatype_tkey;
1089*00b67f09SDavid van Moolenbroek ISC_LINK_INIT(&tkey.common, link);
1090*00b67f09SDavid van Moolenbroek tkey.mctx = msg->mctx;
1091*00b67f09SDavid van Moolenbroek dns_name_init(&tkey.algorithm, NULL);
1092*00b67f09SDavid van Moolenbroek dns_name_clone(key->algorithm, &tkey.algorithm);
1093*00b67f09SDavid van Moolenbroek tkey.inception = tkey.expire = 0;
1094*00b67f09SDavid van Moolenbroek tkey.mode = DNS_TKEYMODE_DELETE;
1095*00b67f09SDavid van Moolenbroek tkey.error = 0;
1096*00b67f09SDavid van Moolenbroek tkey.keylen = tkey.otherlen = 0;
1097*00b67f09SDavid van Moolenbroek tkey.key = tkey.other = NULL;
1098*00b67f09SDavid van Moolenbroek
1099*00b67f09SDavid van Moolenbroek return (buildquery(msg, &key->name, &tkey, ISC_FALSE));
1100*00b67f09SDavid van Moolenbroek }
1101*00b67f09SDavid van Moolenbroek
1102*00b67f09SDavid van Moolenbroek static isc_result_t
find_tkey(dns_message_t * msg,dns_name_t ** name,dns_rdata_t * rdata,int section)1103*00b67f09SDavid van Moolenbroek find_tkey(dns_message_t *msg, dns_name_t **name, dns_rdata_t *rdata,
1104*00b67f09SDavid van Moolenbroek int section)
1105*00b67f09SDavid van Moolenbroek {
1106*00b67f09SDavid van Moolenbroek dns_rdataset_t *tkeyset;
1107*00b67f09SDavid van Moolenbroek isc_result_t result;
1108*00b67f09SDavid van Moolenbroek
1109*00b67f09SDavid van Moolenbroek result = dns_message_firstname(msg, section);
1110*00b67f09SDavid van Moolenbroek while (result == ISC_R_SUCCESS) {
1111*00b67f09SDavid van Moolenbroek *name = NULL;
1112*00b67f09SDavid van Moolenbroek dns_message_currentname(msg, section, name);
1113*00b67f09SDavid van Moolenbroek tkeyset = NULL;
1114*00b67f09SDavid van Moolenbroek result = dns_message_findtype(*name, dns_rdatatype_tkey, 0,
1115*00b67f09SDavid van Moolenbroek &tkeyset);
1116*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS) {
1117*00b67f09SDavid van Moolenbroek result = dns_rdataset_first(tkeyset);
1118*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1119*00b67f09SDavid van Moolenbroek return (result);
1120*00b67f09SDavid van Moolenbroek dns_rdataset_current(tkeyset, rdata);
1121*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1122*00b67f09SDavid van Moolenbroek }
1123*00b67f09SDavid van Moolenbroek result = dns_message_nextname(msg, section);
1124*00b67f09SDavid van Moolenbroek }
1125*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE)
1126*00b67f09SDavid van Moolenbroek return (ISC_R_NOTFOUND);
1127*00b67f09SDavid van Moolenbroek return (result);
1128*00b67f09SDavid van Moolenbroek }
1129*00b67f09SDavid van Moolenbroek
1130*00b67f09SDavid van Moolenbroek isc_result_t
dns_tkey_processdhresponse(dns_message_t * qmsg,dns_message_t * rmsg,dst_key_t * key,isc_buffer_t * nonce,dns_tsigkey_t ** outkey,dns_tsig_keyring_t * ring)1131*00b67f09SDavid van Moolenbroek dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
1132*00b67f09SDavid van Moolenbroek dst_key_t *key, isc_buffer_t *nonce,
1133*00b67f09SDavid van Moolenbroek dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring)
1134*00b67f09SDavid van Moolenbroek {
1135*00b67f09SDavid van Moolenbroek dns_rdata_t qtkeyrdata = DNS_RDATA_INIT, rtkeyrdata = DNS_RDATA_INIT;
1136*00b67f09SDavid van Moolenbroek dns_name_t keyname, *tkeyname, *theirkeyname, *ourkeyname, *tempname;
1137*00b67f09SDavid van Moolenbroek dns_rdataset_t *theirkeyset = NULL, *ourkeyset = NULL;
1138*00b67f09SDavid van Moolenbroek dns_rdata_t theirkeyrdata = DNS_RDATA_INIT;
1139*00b67f09SDavid van Moolenbroek dst_key_t *theirkey = NULL;
1140*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t qtkey, rtkey;
1141*00b67f09SDavid van Moolenbroek unsigned char secretdata[256];
1142*00b67f09SDavid van Moolenbroek unsigned int sharedsize;
1143*00b67f09SDavid van Moolenbroek isc_buffer_t *shared = NULL, secret;
1144*00b67f09SDavid van Moolenbroek isc_region_t r, r2;
1145*00b67f09SDavid van Moolenbroek isc_result_t result;
1146*00b67f09SDavid van Moolenbroek isc_boolean_t freertkey = ISC_FALSE;
1147*00b67f09SDavid van Moolenbroek
1148*00b67f09SDavid van Moolenbroek REQUIRE(qmsg != NULL);
1149*00b67f09SDavid van Moolenbroek REQUIRE(rmsg != NULL);
1150*00b67f09SDavid van Moolenbroek REQUIRE(key != NULL);
1151*00b67f09SDavid van Moolenbroek REQUIRE(dst_key_alg(key) == DNS_KEYALG_DH);
1152*00b67f09SDavid van Moolenbroek REQUIRE(dst_key_isprivate(key));
1153*00b67f09SDavid van Moolenbroek if (outkey != NULL)
1154*00b67f09SDavid van Moolenbroek REQUIRE(*outkey == NULL);
1155*00b67f09SDavid van Moolenbroek
1156*00b67f09SDavid van Moolenbroek if (rmsg->rcode != dns_rcode_noerror)
1157*00b67f09SDavid van Moolenbroek return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
1158*00b67f09SDavid van Moolenbroek RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
1159*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
1160*00b67f09SDavid van Moolenbroek freertkey = ISC_TRUE;
1161*00b67f09SDavid van Moolenbroek
1162*00b67f09SDavid van Moolenbroek RETERR(find_tkey(qmsg, &tempname, &qtkeyrdata,
1163*00b67f09SDavid van Moolenbroek DNS_SECTION_ADDITIONAL));
1164*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
1165*00b67f09SDavid van Moolenbroek
1166*00b67f09SDavid van Moolenbroek if (rtkey.error != dns_rcode_noerror ||
1167*00b67f09SDavid van Moolenbroek rtkey.mode != DNS_TKEYMODE_DIFFIEHELLMAN ||
1168*00b67f09SDavid van Moolenbroek rtkey.mode != qtkey.mode ||
1169*00b67f09SDavid van Moolenbroek !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm) ||
1170*00b67f09SDavid van Moolenbroek rmsg->rcode != dns_rcode_noerror) {
1171*00b67f09SDavid van Moolenbroek tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
1172*00b67f09SDavid van Moolenbroek "or error set(1)");
1173*00b67f09SDavid van Moolenbroek result = DNS_R_INVALIDTKEY;
1174*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&qtkey);
1175*00b67f09SDavid van Moolenbroek goto failure;
1176*00b67f09SDavid van Moolenbroek }
1177*00b67f09SDavid van Moolenbroek
1178*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&qtkey);
1179*00b67f09SDavid van Moolenbroek
1180*00b67f09SDavid van Moolenbroek dns_name_init(&keyname, NULL);
1181*00b67f09SDavid van Moolenbroek dns_name_clone(dst_key_name(key), &keyname);
1182*00b67f09SDavid van Moolenbroek
1183*00b67f09SDavid van Moolenbroek ourkeyname = NULL;
1184*00b67f09SDavid van Moolenbroek ourkeyset = NULL;
1185*00b67f09SDavid van Moolenbroek RETERR(dns_message_findname(rmsg, DNS_SECTION_ANSWER, &keyname,
1186*00b67f09SDavid van Moolenbroek dns_rdatatype_key, 0, &ourkeyname,
1187*00b67f09SDavid van Moolenbroek &ourkeyset));
1188*00b67f09SDavid van Moolenbroek
1189*00b67f09SDavid van Moolenbroek result = dns_message_firstname(rmsg, DNS_SECTION_ANSWER);
1190*00b67f09SDavid van Moolenbroek while (result == ISC_R_SUCCESS) {
1191*00b67f09SDavid van Moolenbroek theirkeyname = NULL;
1192*00b67f09SDavid van Moolenbroek dns_message_currentname(rmsg, DNS_SECTION_ANSWER,
1193*00b67f09SDavid van Moolenbroek &theirkeyname);
1194*00b67f09SDavid van Moolenbroek if (dns_name_equal(theirkeyname, ourkeyname))
1195*00b67f09SDavid van Moolenbroek goto next;
1196*00b67f09SDavid van Moolenbroek theirkeyset = NULL;
1197*00b67f09SDavid van Moolenbroek result = dns_message_findtype(theirkeyname, dns_rdatatype_key,
1198*00b67f09SDavid van Moolenbroek 0, &theirkeyset);
1199*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS) {
1200*00b67f09SDavid van Moolenbroek RETERR(dns_rdataset_first(theirkeyset));
1201*00b67f09SDavid van Moolenbroek break;
1202*00b67f09SDavid van Moolenbroek }
1203*00b67f09SDavid van Moolenbroek next:
1204*00b67f09SDavid van Moolenbroek result = dns_message_nextname(rmsg, DNS_SECTION_ANSWER);
1205*00b67f09SDavid van Moolenbroek }
1206*00b67f09SDavid van Moolenbroek
1207*00b67f09SDavid van Moolenbroek if (theirkeyset == NULL) {
1208*00b67f09SDavid van Moolenbroek tkey_log("dns_tkey_processdhresponse: failed to find server "
1209*00b67f09SDavid van Moolenbroek "key");
1210*00b67f09SDavid van Moolenbroek result = ISC_R_NOTFOUND;
1211*00b67f09SDavid van Moolenbroek goto failure;
1212*00b67f09SDavid van Moolenbroek }
1213*00b67f09SDavid van Moolenbroek
1214*00b67f09SDavid van Moolenbroek dns_rdataset_current(theirkeyset, &theirkeyrdata);
1215*00b67f09SDavid van Moolenbroek RETERR(dns_dnssec_keyfromrdata(theirkeyname, &theirkeyrdata,
1216*00b67f09SDavid van Moolenbroek rmsg->mctx, &theirkey));
1217*00b67f09SDavid van Moolenbroek
1218*00b67f09SDavid van Moolenbroek RETERR(dst_key_secretsize(key, &sharedsize));
1219*00b67f09SDavid van Moolenbroek RETERR(isc_buffer_allocate(rmsg->mctx, &shared, sharedsize));
1220*00b67f09SDavid van Moolenbroek
1221*00b67f09SDavid van Moolenbroek RETERR(dst_key_computesecret(theirkey, key, shared));
1222*00b67f09SDavid van Moolenbroek
1223*00b67f09SDavid van Moolenbroek isc_buffer_init(&secret, secretdata, sizeof(secretdata));
1224*00b67f09SDavid van Moolenbroek
1225*00b67f09SDavid van Moolenbroek r.base = rtkey.key;
1226*00b67f09SDavid van Moolenbroek r.length = rtkey.keylen;
1227*00b67f09SDavid van Moolenbroek if (nonce != NULL)
1228*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(nonce, &r2);
1229*00b67f09SDavid van Moolenbroek else {
1230*00b67f09SDavid van Moolenbroek r2.base = isc_mem_get(rmsg->mctx, 0);
1231*00b67f09SDavid van Moolenbroek r2.length = 0;
1232*00b67f09SDavid van Moolenbroek }
1233*00b67f09SDavid van Moolenbroek RETERR(compute_secret(shared, &r2, &r, &secret));
1234*00b67f09SDavid van Moolenbroek if (nonce == NULL)
1235*00b67f09SDavid van Moolenbroek isc_mem_put(rmsg->mctx, r2.base, 0);
1236*00b67f09SDavid van Moolenbroek
1237*00b67f09SDavid van Moolenbroek isc_buffer_usedregion(&secret, &r);
1238*00b67f09SDavid van Moolenbroek result = dns_tsigkey_create(tkeyname, &rtkey.algorithm,
1239*00b67f09SDavid van Moolenbroek r.base, r.length, ISC_TRUE,
1240*00b67f09SDavid van Moolenbroek NULL, rtkey.inception, rtkey.expire,
1241*00b67f09SDavid van Moolenbroek rmsg->mctx, ring, outkey);
1242*00b67f09SDavid van Moolenbroek isc_buffer_free(&shared);
1243*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&rtkey);
1244*00b67f09SDavid van Moolenbroek dst_key_free(&theirkey);
1245*00b67f09SDavid van Moolenbroek return (result);
1246*00b67f09SDavid van Moolenbroek
1247*00b67f09SDavid van Moolenbroek failure:
1248*00b67f09SDavid van Moolenbroek if (shared != NULL)
1249*00b67f09SDavid van Moolenbroek isc_buffer_free(&shared);
1250*00b67f09SDavid van Moolenbroek
1251*00b67f09SDavid van Moolenbroek if (theirkey != NULL)
1252*00b67f09SDavid van Moolenbroek dst_key_free(&theirkey);
1253*00b67f09SDavid van Moolenbroek
1254*00b67f09SDavid van Moolenbroek if (freertkey)
1255*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&rtkey);
1256*00b67f09SDavid van Moolenbroek
1257*00b67f09SDavid van Moolenbroek return (result);
1258*00b67f09SDavid van Moolenbroek }
1259*00b67f09SDavid van Moolenbroek
1260*00b67f09SDavid van Moolenbroek isc_result_t
dns_tkey_processgssresponse(dns_message_t * qmsg,dns_message_t * rmsg,dns_name_t * gname,gss_ctx_id_t * context,isc_buffer_t * outtoken,dns_tsigkey_t ** outkey,dns_tsig_keyring_t * ring,char ** err_message)1261*00b67f09SDavid van Moolenbroek dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
1262*00b67f09SDavid van Moolenbroek dns_name_t *gname, gss_ctx_id_t *context,
1263*00b67f09SDavid van Moolenbroek isc_buffer_t *outtoken, dns_tsigkey_t **outkey,
1264*00b67f09SDavid van Moolenbroek dns_tsig_keyring_t *ring, char **err_message)
1265*00b67f09SDavid van Moolenbroek {
1266*00b67f09SDavid van Moolenbroek dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
1267*00b67f09SDavid van Moolenbroek dns_name_t *tkeyname;
1268*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t rtkey, qtkey;
1269*00b67f09SDavid van Moolenbroek dst_key_t *dstkey = NULL;
1270*00b67f09SDavid van Moolenbroek isc_buffer_t intoken;
1271*00b67f09SDavid van Moolenbroek isc_result_t result;
1272*00b67f09SDavid van Moolenbroek unsigned char array[1024];
1273*00b67f09SDavid van Moolenbroek
1274*00b67f09SDavid van Moolenbroek REQUIRE(outtoken != NULL);
1275*00b67f09SDavid van Moolenbroek REQUIRE(qmsg != NULL);
1276*00b67f09SDavid van Moolenbroek REQUIRE(rmsg != NULL);
1277*00b67f09SDavid van Moolenbroek REQUIRE(gname != NULL);
1278*00b67f09SDavid van Moolenbroek REQUIRE(ring != NULL);
1279*00b67f09SDavid van Moolenbroek if (outkey != NULL)
1280*00b67f09SDavid van Moolenbroek REQUIRE(*outkey == NULL);
1281*00b67f09SDavid van Moolenbroek
1282*00b67f09SDavid van Moolenbroek if (rmsg->rcode != dns_rcode_noerror)
1283*00b67f09SDavid van Moolenbroek return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
1284*00b67f09SDavid van Moolenbroek RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
1285*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
1286*00b67f09SDavid van Moolenbroek
1287*00b67f09SDavid van Moolenbroek /*
1288*00b67f09SDavid van Moolenbroek * Win2k puts the item in the ANSWER section, while the RFC
1289*00b67f09SDavid van Moolenbroek * specifies it should be in the ADDITIONAL section. Check first
1290*00b67f09SDavid van Moolenbroek * where it should be, and then where it may be.
1291*00b67f09SDavid van Moolenbroek */
1292*00b67f09SDavid van Moolenbroek result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
1293*00b67f09SDavid van Moolenbroek DNS_SECTION_ADDITIONAL);
1294*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOTFOUND)
1295*00b67f09SDavid van Moolenbroek result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
1296*00b67f09SDavid van Moolenbroek DNS_SECTION_ANSWER);
1297*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
1298*00b67f09SDavid van Moolenbroek goto failure;
1299*00b67f09SDavid van Moolenbroek
1300*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
1301*00b67f09SDavid van Moolenbroek
1302*00b67f09SDavid van Moolenbroek if (rtkey.error != dns_rcode_noerror ||
1303*00b67f09SDavid van Moolenbroek rtkey.mode != DNS_TKEYMODE_GSSAPI ||
1304*00b67f09SDavid van Moolenbroek !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm)) {
1305*00b67f09SDavid van Moolenbroek tkey_log("dns_tkey_processgssresponse: tkey mode invalid "
1306*00b67f09SDavid van Moolenbroek "or error set(2) %d", rtkey.error);
1307*00b67f09SDavid van Moolenbroek _dns_tkey_dumpmessage(qmsg);
1308*00b67f09SDavid van Moolenbroek _dns_tkey_dumpmessage(rmsg);
1309*00b67f09SDavid van Moolenbroek result = DNS_R_INVALIDTKEY;
1310*00b67f09SDavid van Moolenbroek goto failure;
1311*00b67f09SDavid van Moolenbroek }
1312*00b67f09SDavid van Moolenbroek
1313*00b67f09SDavid van Moolenbroek isc_buffer_init(outtoken, array, sizeof(array));
1314*00b67f09SDavid van Moolenbroek isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
1315*00b67f09SDavid van Moolenbroek RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context,
1316*00b67f09SDavid van Moolenbroek ring->mctx, err_message));
1317*00b67f09SDavid van Moolenbroek
1318*00b67f09SDavid van Moolenbroek RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
1319*00b67f09SDavid van Moolenbroek &dstkey, NULL));
1320*00b67f09SDavid van Moolenbroek
1321*00b67f09SDavid van Moolenbroek RETERR(dns_tsigkey_createfromkey(tkeyname, DNS_TSIG_GSSAPI_NAME,
1322*00b67f09SDavid van Moolenbroek dstkey, ISC_FALSE, NULL,
1323*00b67f09SDavid van Moolenbroek rtkey.inception, rtkey.expire,
1324*00b67f09SDavid van Moolenbroek ring->mctx, ring, outkey));
1325*00b67f09SDavid van Moolenbroek dst_key_free(&dstkey);
1326*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&rtkey);
1327*00b67f09SDavid van Moolenbroek return (result);
1328*00b67f09SDavid van Moolenbroek
1329*00b67f09SDavid van Moolenbroek failure:
1330*00b67f09SDavid van Moolenbroek /*
1331*00b67f09SDavid van Moolenbroek * XXXSRA This probably leaks memory from rtkey and qtkey.
1332*00b67f09SDavid van Moolenbroek */
1333*00b67f09SDavid van Moolenbroek if (dstkey != NULL)
1334*00b67f09SDavid van Moolenbroek dst_key_free(&dstkey);
1335*00b67f09SDavid van Moolenbroek return (result);
1336*00b67f09SDavid van Moolenbroek }
1337*00b67f09SDavid van Moolenbroek
1338*00b67f09SDavid van Moolenbroek isc_result_t
dns_tkey_processdeleteresponse(dns_message_t * qmsg,dns_message_t * rmsg,dns_tsig_keyring_t * ring)1339*00b67f09SDavid van Moolenbroek dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
1340*00b67f09SDavid van Moolenbroek dns_tsig_keyring_t *ring)
1341*00b67f09SDavid van Moolenbroek {
1342*00b67f09SDavid van Moolenbroek dns_rdata_t qtkeyrdata = DNS_RDATA_INIT, rtkeyrdata = DNS_RDATA_INIT;
1343*00b67f09SDavid van Moolenbroek dns_name_t *tkeyname, *tempname;
1344*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t qtkey, rtkey;
1345*00b67f09SDavid van Moolenbroek dns_tsigkey_t *tsigkey = NULL;
1346*00b67f09SDavid van Moolenbroek isc_result_t result;
1347*00b67f09SDavid van Moolenbroek
1348*00b67f09SDavid van Moolenbroek REQUIRE(qmsg != NULL);
1349*00b67f09SDavid van Moolenbroek REQUIRE(rmsg != NULL);
1350*00b67f09SDavid van Moolenbroek
1351*00b67f09SDavid van Moolenbroek if (rmsg->rcode != dns_rcode_noerror)
1352*00b67f09SDavid van Moolenbroek return(ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
1353*00b67f09SDavid van Moolenbroek
1354*00b67f09SDavid van Moolenbroek RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
1355*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
1356*00b67f09SDavid van Moolenbroek
1357*00b67f09SDavid van Moolenbroek RETERR(find_tkey(qmsg, &tempname, &qtkeyrdata,
1358*00b67f09SDavid van Moolenbroek DNS_SECTION_ADDITIONAL));
1359*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
1360*00b67f09SDavid van Moolenbroek
1361*00b67f09SDavid van Moolenbroek if (rtkey.error != dns_rcode_noerror ||
1362*00b67f09SDavid van Moolenbroek rtkey.mode != DNS_TKEYMODE_DELETE ||
1363*00b67f09SDavid van Moolenbroek rtkey.mode != qtkey.mode ||
1364*00b67f09SDavid van Moolenbroek !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm) ||
1365*00b67f09SDavid van Moolenbroek rmsg->rcode != dns_rcode_noerror) {
1366*00b67f09SDavid van Moolenbroek tkey_log("dns_tkey_processdeleteresponse: tkey mode invalid "
1367*00b67f09SDavid van Moolenbroek "or error set(3)");
1368*00b67f09SDavid van Moolenbroek result = DNS_R_INVALIDTKEY;
1369*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&qtkey);
1370*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&rtkey);
1371*00b67f09SDavid van Moolenbroek goto failure;
1372*00b67f09SDavid van Moolenbroek }
1373*00b67f09SDavid van Moolenbroek
1374*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&qtkey);
1375*00b67f09SDavid van Moolenbroek
1376*00b67f09SDavid van Moolenbroek RETERR(dns_tsigkey_find(&tsigkey, tkeyname, &rtkey.algorithm, ring));
1377*00b67f09SDavid van Moolenbroek
1378*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&rtkey);
1379*00b67f09SDavid van Moolenbroek
1380*00b67f09SDavid van Moolenbroek /*
1381*00b67f09SDavid van Moolenbroek * Mark the key as deleted.
1382*00b67f09SDavid van Moolenbroek */
1383*00b67f09SDavid van Moolenbroek dns_tsigkey_setdeleted(tsigkey);
1384*00b67f09SDavid van Moolenbroek /*
1385*00b67f09SDavid van Moolenbroek * Release the reference.
1386*00b67f09SDavid van Moolenbroek */
1387*00b67f09SDavid van Moolenbroek dns_tsigkey_detach(&tsigkey);
1388*00b67f09SDavid van Moolenbroek
1389*00b67f09SDavid van Moolenbroek failure:
1390*00b67f09SDavid van Moolenbroek return (result);
1391*00b67f09SDavid van Moolenbroek }
1392*00b67f09SDavid van Moolenbroek
1393*00b67f09SDavid van Moolenbroek isc_result_t
dns_tkey_gssnegotiate(dns_message_t * qmsg,dns_message_t * rmsg,dns_name_t * server,gss_ctx_id_t * context,dns_tsigkey_t ** outkey,dns_tsig_keyring_t * ring,isc_boolean_t win2k,char ** err_message)1394*00b67f09SDavid van Moolenbroek dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg,
1395*00b67f09SDavid van Moolenbroek dns_name_t *server, gss_ctx_id_t *context,
1396*00b67f09SDavid van Moolenbroek dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring,
1397*00b67f09SDavid van Moolenbroek isc_boolean_t win2k, char **err_message)
1398*00b67f09SDavid van Moolenbroek {
1399*00b67f09SDavid van Moolenbroek dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
1400*00b67f09SDavid van Moolenbroek dns_name_t *tkeyname;
1401*00b67f09SDavid van Moolenbroek dns_rdata_tkey_t rtkey, qtkey;
1402*00b67f09SDavid van Moolenbroek isc_buffer_t intoken, outtoken;
1403*00b67f09SDavid van Moolenbroek dst_key_t *dstkey = NULL;
1404*00b67f09SDavid van Moolenbroek isc_result_t result;
1405*00b67f09SDavid van Moolenbroek unsigned char array[1024];
1406*00b67f09SDavid van Moolenbroek isc_boolean_t freertkey = ISC_FALSE;
1407*00b67f09SDavid van Moolenbroek
1408*00b67f09SDavid van Moolenbroek REQUIRE(qmsg != NULL);
1409*00b67f09SDavid van Moolenbroek REQUIRE(rmsg != NULL);
1410*00b67f09SDavid van Moolenbroek REQUIRE(server != NULL);
1411*00b67f09SDavid van Moolenbroek if (outkey != NULL)
1412*00b67f09SDavid van Moolenbroek REQUIRE(*outkey == NULL);
1413*00b67f09SDavid van Moolenbroek
1414*00b67f09SDavid van Moolenbroek if (rmsg->rcode != dns_rcode_noerror)
1415*00b67f09SDavid van Moolenbroek return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
1416*00b67f09SDavid van Moolenbroek
1417*00b67f09SDavid van Moolenbroek RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
1418*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
1419*00b67f09SDavid van Moolenbroek freertkey = ISC_TRUE;
1420*00b67f09SDavid van Moolenbroek
1421*00b67f09SDavid van Moolenbroek if (win2k == ISC_TRUE)
1422*00b67f09SDavid van Moolenbroek RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
1423*00b67f09SDavid van Moolenbroek DNS_SECTION_ANSWER));
1424*00b67f09SDavid van Moolenbroek else
1425*00b67f09SDavid van Moolenbroek RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
1426*00b67f09SDavid van Moolenbroek DNS_SECTION_ADDITIONAL));
1427*00b67f09SDavid van Moolenbroek
1428*00b67f09SDavid van Moolenbroek RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
1429*00b67f09SDavid van Moolenbroek
1430*00b67f09SDavid van Moolenbroek if (rtkey.error != dns_rcode_noerror ||
1431*00b67f09SDavid van Moolenbroek rtkey.mode != DNS_TKEYMODE_GSSAPI ||
1432*00b67f09SDavid van Moolenbroek !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm))
1433*00b67f09SDavid van Moolenbroek {
1434*00b67f09SDavid van Moolenbroek tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
1435*00b67f09SDavid van Moolenbroek "or error set(4)");
1436*00b67f09SDavid van Moolenbroek result = DNS_R_INVALIDTKEY;
1437*00b67f09SDavid van Moolenbroek goto failure;
1438*00b67f09SDavid van Moolenbroek }
1439*00b67f09SDavid van Moolenbroek
1440*00b67f09SDavid van Moolenbroek isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
1441*00b67f09SDavid van Moolenbroek isc_buffer_init(&outtoken, array, sizeof(array));
1442*00b67f09SDavid van Moolenbroek
1443*00b67f09SDavid van Moolenbroek result = dst_gssapi_initctx(server, &intoken, &outtoken, context,
1444*00b67f09SDavid van Moolenbroek ring->mctx, err_message);
1445*00b67f09SDavid van Moolenbroek if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
1446*00b67f09SDavid van Moolenbroek return (result);
1447*00b67f09SDavid van Moolenbroek
1448*00b67f09SDavid van Moolenbroek RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
1449*00b67f09SDavid van Moolenbroek &dstkey, NULL));
1450*00b67f09SDavid van Moolenbroek
1451*00b67f09SDavid van Moolenbroek /*
1452*00b67f09SDavid van Moolenbroek * XXXSRA This seems confused. If we got CONTINUE from initctx,
1453*00b67f09SDavid van Moolenbroek * the GSS negotiation hasn't completed yet, so we can't sign
1454*00b67f09SDavid van Moolenbroek * anything yet.
1455*00b67f09SDavid van Moolenbroek */
1456*00b67f09SDavid van Moolenbroek
1457*00b67f09SDavid van Moolenbroek RETERR(dns_tsigkey_createfromkey(tkeyname,
1458*00b67f09SDavid van Moolenbroek (win2k
1459*00b67f09SDavid van Moolenbroek ? DNS_TSIG_GSSAPIMS_NAME
1460*00b67f09SDavid van Moolenbroek : DNS_TSIG_GSSAPI_NAME),
1461*00b67f09SDavid van Moolenbroek dstkey, ISC_TRUE, NULL,
1462*00b67f09SDavid van Moolenbroek rtkey.inception, rtkey.expire,
1463*00b67f09SDavid van Moolenbroek ring->mctx, ring, outkey));
1464*00b67f09SDavid van Moolenbroek dst_key_free(&dstkey);
1465*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&rtkey);
1466*00b67f09SDavid van Moolenbroek return (result);
1467*00b67f09SDavid van Moolenbroek
1468*00b67f09SDavid van Moolenbroek failure:
1469*00b67f09SDavid van Moolenbroek /*
1470*00b67f09SDavid van Moolenbroek * XXXSRA This probably leaks memory from qtkey.
1471*00b67f09SDavid van Moolenbroek */
1472*00b67f09SDavid van Moolenbroek if (freertkey)
1473*00b67f09SDavid van Moolenbroek dns_rdata_freestruct(&rtkey);
1474*00b67f09SDavid van Moolenbroek if (dstkey != NULL)
1475*00b67f09SDavid van Moolenbroek dst_key_free(&dstkey);
1476*00b67f09SDavid van Moolenbroek return (result);
1477*00b67f09SDavid van Moolenbroek }
1478