xref: /minix3/external/bsd/bind/dist/lib/dns/gssapi_link.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: gssapi_link.c,v 1.8 2014/12/10 04:37:58 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2009, 2011-2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 2000-2002  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: gssapi_link.c,v 1.17 2011/03/28 05:32:16 marka Exp
22*00b67f09SDavid van Moolenbroek  */
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #ifdef GSSAPI
27*00b67f09SDavid van Moolenbroek 
28*00b67f09SDavid van Moolenbroek #include <isc/base64.h>
29*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
30*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
31*00b67f09SDavid van Moolenbroek #include <isc/string.h>
32*00b67f09SDavid van Moolenbroek #include <isc/util.h>
33*00b67f09SDavid van Moolenbroek 
34*00b67f09SDavid van Moolenbroek #include <dst/result.h>
35*00b67f09SDavid van Moolenbroek 
36*00b67f09SDavid van Moolenbroek #include "dst_internal.h"
37*00b67f09SDavid van Moolenbroek #include "dst_parse.h"
38*00b67f09SDavid van Moolenbroek 
39*00b67f09SDavid van Moolenbroek #include <dst/gssapi.h>
40*00b67f09SDavid van Moolenbroek 
41*00b67f09SDavid van Moolenbroek #define INITIAL_BUFFER_SIZE 1024
42*00b67f09SDavid van Moolenbroek #define BUFFER_EXTRA 1024
43*00b67f09SDavid van Moolenbroek 
44*00b67f09SDavid van Moolenbroek #define REGION_TO_GBUFFER(r, gb) \
45*00b67f09SDavid van Moolenbroek 	do { \
46*00b67f09SDavid van Moolenbroek 		(gb).length = (r).length; \
47*00b67f09SDavid van Moolenbroek 		(gb).value = (r).base; \
48*00b67f09SDavid van Moolenbroek 	} while (/*CONSTCOND*/0)
49*00b67f09SDavid van Moolenbroek 
50*00b67f09SDavid van Moolenbroek #define GBUFFER_TO_REGION(gb, r) \
51*00b67f09SDavid van Moolenbroek 	do { \
52*00b67f09SDavid van Moolenbroek 	  (r).length = (unsigned int)(gb).length; \
53*00b67f09SDavid van Moolenbroek 		(r).base = (gb).value; \
54*00b67f09SDavid van Moolenbroek 	} while (/*CONSTCOND*/0)
55*00b67f09SDavid van Moolenbroek 
56*00b67f09SDavid van Moolenbroek 
57*00b67f09SDavid van Moolenbroek struct dst_gssapi_signverifyctx {
58*00b67f09SDavid van Moolenbroek 	isc_buffer_t *buffer;
59*00b67f09SDavid van Moolenbroek };
60*00b67f09SDavid van Moolenbroek 
61*00b67f09SDavid van Moolenbroek /*%
62*00b67f09SDavid van Moolenbroek  * Allocate a temporary "context" for use in gathering data for signing
63*00b67f09SDavid van Moolenbroek  * or verifying.
64*00b67f09SDavid van Moolenbroek  */
65*00b67f09SDavid van Moolenbroek static isc_result_t
gssapi_create_signverify_ctx(dst_key_t * key,dst_context_t * dctx)66*00b67f09SDavid van Moolenbroek gssapi_create_signverify_ctx(dst_key_t *key, dst_context_t *dctx) {
67*00b67f09SDavid van Moolenbroek 	dst_gssapi_signverifyctx_t *ctx;
68*00b67f09SDavid van Moolenbroek 	isc_result_t result;
69*00b67f09SDavid van Moolenbroek 
70*00b67f09SDavid van Moolenbroek 	UNUSED(key);
71*00b67f09SDavid van Moolenbroek 
72*00b67f09SDavid van Moolenbroek 	ctx = isc_mem_get(dctx->mctx, sizeof(dst_gssapi_signverifyctx_t));
73*00b67f09SDavid van Moolenbroek 	if (ctx == NULL)
74*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
75*00b67f09SDavid van Moolenbroek 	ctx->buffer = NULL;
76*00b67f09SDavid van Moolenbroek 	result = isc_buffer_allocate(dctx->mctx, &ctx->buffer,
77*00b67f09SDavid van Moolenbroek 				     INITIAL_BUFFER_SIZE);
78*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
79*00b67f09SDavid van Moolenbroek 		isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
80*00b67f09SDavid van Moolenbroek 		return (result);
81*00b67f09SDavid van Moolenbroek 	}
82*00b67f09SDavid van Moolenbroek 
83*00b67f09SDavid van Moolenbroek 	dctx->ctxdata.gssctx = ctx;
84*00b67f09SDavid van Moolenbroek 
85*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
86*00b67f09SDavid van Moolenbroek }
87*00b67f09SDavid van Moolenbroek 
88*00b67f09SDavid van Moolenbroek /*%
89*00b67f09SDavid van Moolenbroek  * Destroy the temporary sign/verify context.
90*00b67f09SDavid van Moolenbroek  */
91*00b67f09SDavid van Moolenbroek static void
gssapi_destroy_signverify_ctx(dst_context_t * dctx)92*00b67f09SDavid van Moolenbroek gssapi_destroy_signverify_ctx(dst_context_t *dctx) {
93*00b67f09SDavid van Moolenbroek 	dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
94*00b67f09SDavid van Moolenbroek 
95*00b67f09SDavid van Moolenbroek 	if (ctx != NULL) {
96*00b67f09SDavid van Moolenbroek 		if (ctx->buffer != NULL)
97*00b67f09SDavid van Moolenbroek 			isc_buffer_free(&ctx->buffer);
98*00b67f09SDavid van Moolenbroek 		isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
99*00b67f09SDavid van Moolenbroek 		dctx->ctxdata.gssctx = NULL;
100*00b67f09SDavid van Moolenbroek 	}
101*00b67f09SDavid van Moolenbroek }
102*00b67f09SDavid van Moolenbroek 
103*00b67f09SDavid van Moolenbroek /*%
104*00b67f09SDavid van Moolenbroek  * Add data to our running buffer of data we will be signing or verifying.
105*00b67f09SDavid van Moolenbroek  * This code will see if the new data will fit in our existing buffer, and
106*00b67f09SDavid van Moolenbroek  * copy it in if it will.  If not, it will attempt to allocate a larger
107*00b67f09SDavid van Moolenbroek  * buffer and copy old+new into it, and free the old buffer.
108*00b67f09SDavid van Moolenbroek  */
109*00b67f09SDavid van Moolenbroek static isc_result_t
gssapi_adddata(dst_context_t * dctx,const isc_region_t * data)110*00b67f09SDavid van Moolenbroek gssapi_adddata(dst_context_t *dctx, const isc_region_t *data) {
111*00b67f09SDavid van Moolenbroek 	dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
112*00b67f09SDavid van Moolenbroek 	isc_buffer_t *newbuffer = NULL;
113*00b67f09SDavid van Moolenbroek 	isc_region_t r;
114*00b67f09SDavid van Moolenbroek 	unsigned int length;
115*00b67f09SDavid van Moolenbroek 	isc_result_t result;
116*00b67f09SDavid van Moolenbroek 
117*00b67f09SDavid van Moolenbroek 	result = isc_buffer_copyregion(ctx->buffer, data);
118*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
119*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
120*00b67f09SDavid van Moolenbroek 
121*00b67f09SDavid van Moolenbroek 	length = isc_buffer_length(ctx->buffer) + data->length + BUFFER_EXTRA;
122*00b67f09SDavid van Moolenbroek 
123*00b67f09SDavid van Moolenbroek 	result = isc_buffer_allocate(dctx->mctx, &newbuffer, length);
124*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
125*00b67f09SDavid van Moolenbroek 		return (result);
126*00b67f09SDavid van Moolenbroek 
127*00b67f09SDavid van Moolenbroek 	isc_buffer_usedregion(ctx->buffer, &r);
128*00b67f09SDavid van Moolenbroek 	(void)isc_buffer_copyregion(newbuffer, &r);
129*00b67f09SDavid van Moolenbroek 	(void)isc_buffer_copyregion(newbuffer, data);
130*00b67f09SDavid van Moolenbroek 
131*00b67f09SDavid van Moolenbroek 	isc_buffer_free(&ctx->buffer);
132*00b67f09SDavid van Moolenbroek 	ctx->buffer = newbuffer;
133*00b67f09SDavid van Moolenbroek 
134*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
135*00b67f09SDavid van Moolenbroek }
136*00b67f09SDavid van Moolenbroek 
137*00b67f09SDavid van Moolenbroek /*%
138*00b67f09SDavid van Moolenbroek  * Sign.
139*00b67f09SDavid van Moolenbroek  */
140*00b67f09SDavid van Moolenbroek static isc_result_t
gssapi_sign(dst_context_t * dctx,isc_buffer_t * sig)141*00b67f09SDavid van Moolenbroek gssapi_sign(dst_context_t *dctx, isc_buffer_t *sig) {
142*00b67f09SDavid van Moolenbroek 	dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
143*00b67f09SDavid van Moolenbroek 	isc_region_t message;
144*00b67f09SDavid van Moolenbroek 	gss_buffer_desc gmessage, gsig;
145*00b67f09SDavid van Moolenbroek 	OM_uint32 minor, gret;
146*00b67f09SDavid van Moolenbroek 	gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
147*00b67f09SDavid van Moolenbroek 	char buf[1024];
148*00b67f09SDavid van Moolenbroek 
149*00b67f09SDavid van Moolenbroek 	/*
150*00b67f09SDavid van Moolenbroek 	 * Convert the data we wish to sign into a structure gssapi can
151*00b67f09SDavid van Moolenbroek 	 * understand.
152*00b67f09SDavid van Moolenbroek 	 */
153*00b67f09SDavid van Moolenbroek 	isc_buffer_usedregion(ctx->buffer, &message);
154*00b67f09SDavid van Moolenbroek 	REGION_TO_GBUFFER(message, gmessage);
155*00b67f09SDavid van Moolenbroek 
156*00b67f09SDavid van Moolenbroek 	/*
157*00b67f09SDavid van Moolenbroek 	 * Generate the signature.
158*00b67f09SDavid van Moolenbroek 	 */
159*00b67f09SDavid van Moolenbroek 	gret = gss_get_mic(&minor, gssctx, GSS_C_QOP_DEFAULT, &gmessage,
160*00b67f09SDavid van Moolenbroek 			   &gsig);
161*00b67f09SDavid van Moolenbroek 
162*00b67f09SDavid van Moolenbroek 	/*
163*00b67f09SDavid van Moolenbroek 	 * If it did not complete, we log the result and return a generic
164*00b67f09SDavid van Moolenbroek 	 * failure code.
165*00b67f09SDavid van Moolenbroek 	 */
166*00b67f09SDavid van Moolenbroek 	if (gret != GSS_S_COMPLETE) {
167*00b67f09SDavid van Moolenbroek 		gss_log(3, "GSS sign error: %s",
168*00b67f09SDavid van Moolenbroek 			gss_error_tostring(gret, minor, buf, sizeof(buf)));
169*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
170*00b67f09SDavid van Moolenbroek 	}
171*00b67f09SDavid van Moolenbroek 
172*00b67f09SDavid van Moolenbroek 	/*
173*00b67f09SDavid van Moolenbroek 	 * If it will not fit in our allocated buffer, return that we need
174*00b67f09SDavid van Moolenbroek 	 * more space.
175*00b67f09SDavid van Moolenbroek 	 */
176*00b67f09SDavid van Moolenbroek 	if (gsig.length > isc_buffer_availablelength(sig)) {
177*00b67f09SDavid van Moolenbroek 		gss_release_buffer(&minor, &gsig);
178*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
179*00b67f09SDavid van Moolenbroek 	}
180*00b67f09SDavid van Moolenbroek 
181*00b67f09SDavid van Moolenbroek 	/*
182*00b67f09SDavid van Moolenbroek 	 * Copy the output into our buffer space, and release the gssapi
183*00b67f09SDavid van Moolenbroek 	 * allocated space.
184*00b67f09SDavid van Moolenbroek 	 */
185*00b67f09SDavid van Moolenbroek 	isc_buffer_putmem(sig, gsig.value, (unsigned int)gsig.length);
186*00b67f09SDavid van Moolenbroek 	if (gsig.length != 0U)
187*00b67f09SDavid van Moolenbroek 		gss_release_buffer(&minor, &gsig);
188*00b67f09SDavid van Moolenbroek 
189*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
190*00b67f09SDavid van Moolenbroek }
191*00b67f09SDavid van Moolenbroek 
192*00b67f09SDavid van Moolenbroek /*%
193*00b67f09SDavid van Moolenbroek  * Verify.
194*00b67f09SDavid van Moolenbroek  */
195*00b67f09SDavid van Moolenbroek static isc_result_t
gssapi_verify(dst_context_t * dctx,const isc_region_t * sig)196*00b67f09SDavid van Moolenbroek gssapi_verify(dst_context_t *dctx, const isc_region_t *sig) {
197*00b67f09SDavid van Moolenbroek 	dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
198*00b67f09SDavid van Moolenbroek 	isc_region_t message, r;
199*00b67f09SDavid van Moolenbroek 	gss_buffer_desc gmessage, gsig;
200*00b67f09SDavid van Moolenbroek 	OM_uint32 minor, gret;
201*00b67f09SDavid van Moolenbroek 	gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
202*00b67f09SDavid van Moolenbroek 	unsigned char *buf;
203*00b67f09SDavid van Moolenbroek 	char err[1024];
204*00b67f09SDavid van Moolenbroek 
205*00b67f09SDavid van Moolenbroek 	/*
206*00b67f09SDavid van Moolenbroek 	 * Convert the data we wish to sign into a structure gssapi can
207*00b67f09SDavid van Moolenbroek 	 * understand.
208*00b67f09SDavid van Moolenbroek 	 */
209*00b67f09SDavid van Moolenbroek 	isc_buffer_usedregion(ctx->buffer, &message);
210*00b67f09SDavid van Moolenbroek 	REGION_TO_GBUFFER(message, gmessage);
211*00b67f09SDavid van Moolenbroek 
212*00b67f09SDavid van Moolenbroek 	/*
213*00b67f09SDavid van Moolenbroek 	 * XXXMLG
214*00b67f09SDavid van Moolenbroek 	 * It seem that gss_verify_mic() modifies the signature buffer,
215*00b67f09SDavid van Moolenbroek 	 * at least on Heimdal's implementation.  Copy it here to an allocated
216*00b67f09SDavid van Moolenbroek 	 * buffer.
217*00b67f09SDavid van Moolenbroek 	 */
218*00b67f09SDavid van Moolenbroek 	buf = isc_mem_allocate(dst__memory_pool, sig->length);
219*00b67f09SDavid van Moolenbroek 	if (buf == NULL)
220*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
221*00b67f09SDavid van Moolenbroek 	memmove(buf, sig->base, sig->length);
222*00b67f09SDavid van Moolenbroek 	r.base = buf;
223*00b67f09SDavid van Moolenbroek 	r.length = sig->length;
224*00b67f09SDavid van Moolenbroek 	REGION_TO_GBUFFER(r, gsig);
225*00b67f09SDavid van Moolenbroek 
226*00b67f09SDavid van Moolenbroek 	/*
227*00b67f09SDavid van Moolenbroek 	 * Verify the data.
228*00b67f09SDavid van Moolenbroek 	 */
229*00b67f09SDavid van Moolenbroek 	gret = gss_verify_mic(&minor, gssctx, &gmessage, &gsig, NULL);
230*00b67f09SDavid van Moolenbroek 
231*00b67f09SDavid van Moolenbroek 	isc_mem_free(dst__memory_pool, buf);
232*00b67f09SDavid van Moolenbroek 
233*00b67f09SDavid van Moolenbroek 	/*
234*00b67f09SDavid van Moolenbroek 	 * Convert return codes into something useful to us.
235*00b67f09SDavid van Moolenbroek 	 */
236*00b67f09SDavid van Moolenbroek 	if (gret != GSS_S_COMPLETE) {
237*00b67f09SDavid van Moolenbroek 		gss_log(3, "GSS verify error: %s",
238*00b67f09SDavid van Moolenbroek 			gss_error_tostring(gret, minor, err, sizeof(err)));
239*00b67f09SDavid van Moolenbroek 		if (gret == GSS_S_DEFECTIVE_TOKEN ||
240*00b67f09SDavid van Moolenbroek 		    gret == GSS_S_BAD_SIG ||
241*00b67f09SDavid van Moolenbroek 		    gret == GSS_S_DUPLICATE_TOKEN ||
242*00b67f09SDavid van Moolenbroek 		    gret == GSS_S_OLD_TOKEN ||
243*00b67f09SDavid van Moolenbroek 		    gret == GSS_S_UNSEQ_TOKEN ||
244*00b67f09SDavid van Moolenbroek 		    gret == GSS_S_GAP_TOKEN ||
245*00b67f09SDavid van Moolenbroek 		    gret == GSS_S_CONTEXT_EXPIRED ||
246*00b67f09SDavid van Moolenbroek 		    gret == GSS_S_NO_CONTEXT ||
247*00b67f09SDavid van Moolenbroek 		    gret == GSS_S_FAILURE)
248*00b67f09SDavid van Moolenbroek 			return(DST_R_VERIFYFAILURE);
249*00b67f09SDavid van Moolenbroek 		else
250*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
251*00b67f09SDavid van Moolenbroek 	}
252*00b67f09SDavid van Moolenbroek 
253*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
254*00b67f09SDavid van Moolenbroek }
255*00b67f09SDavid van Moolenbroek 
256*00b67f09SDavid van Moolenbroek static isc_boolean_t
gssapi_compare(const dst_key_t * key1,const dst_key_t * key2)257*00b67f09SDavid van Moolenbroek gssapi_compare(const dst_key_t *key1, const dst_key_t *key2) {
258*00b67f09SDavid van Moolenbroek 	gss_ctx_id_t gsskey1 = key1->keydata.gssctx;
259*00b67f09SDavid van Moolenbroek 	gss_ctx_id_t gsskey2 = key2->keydata.gssctx;
260*00b67f09SDavid van Moolenbroek 
261*00b67f09SDavid van Moolenbroek 	/* No idea */
262*00b67f09SDavid van Moolenbroek 	return (ISC_TF(gsskey1 == gsskey2));
263*00b67f09SDavid van Moolenbroek }
264*00b67f09SDavid van Moolenbroek 
265*00b67f09SDavid van Moolenbroek static isc_result_t
gssapi_generate(dst_key_t * key,int unused,void (* callback)(int))266*00b67f09SDavid van Moolenbroek gssapi_generate(dst_key_t *key, int unused, void (*callback)(int)) {
267*00b67f09SDavid van Moolenbroek 	UNUSED(key);
268*00b67f09SDavid van Moolenbroek 	UNUSED(unused);
269*00b67f09SDavid van Moolenbroek 	UNUSED(callback);
270*00b67f09SDavid van Moolenbroek 
271*00b67f09SDavid van Moolenbroek 	/* No idea */
272*00b67f09SDavid van Moolenbroek 	return (ISC_R_FAILURE);
273*00b67f09SDavid van Moolenbroek }
274*00b67f09SDavid van Moolenbroek 
275*00b67f09SDavid van Moolenbroek static isc_boolean_t
gssapi_isprivate(const dst_key_t * key)276*00b67f09SDavid van Moolenbroek gssapi_isprivate(const dst_key_t *key) {
277*00b67f09SDavid van Moolenbroek 	UNUSED(key);
278*00b67f09SDavid van Moolenbroek 	return (ISC_TRUE);
279*00b67f09SDavid van Moolenbroek }
280*00b67f09SDavid van Moolenbroek 
281*00b67f09SDavid van Moolenbroek static void
gssapi_destroy(dst_key_t * key)282*00b67f09SDavid van Moolenbroek gssapi_destroy(dst_key_t *key) {
283*00b67f09SDavid van Moolenbroek 	REQUIRE(key != NULL);
284*00b67f09SDavid van Moolenbroek 	dst_gssapi_deletectx(key->mctx, &key->keydata.gssctx);
285*00b67f09SDavid van Moolenbroek 	key->keydata.gssctx = NULL;
286*00b67f09SDavid van Moolenbroek }
287*00b67f09SDavid van Moolenbroek 
288*00b67f09SDavid van Moolenbroek static isc_result_t
gssapi_restore(dst_key_t * key,const char * keystr)289*00b67f09SDavid van Moolenbroek gssapi_restore(dst_key_t *key, const char *keystr) {
290*00b67f09SDavid van Moolenbroek 	OM_uint32 major, minor;
291*00b67f09SDavid van Moolenbroek 	unsigned int len;
292*00b67f09SDavid van Moolenbroek 	isc_buffer_t *b = NULL;
293*00b67f09SDavid van Moolenbroek 	isc_region_t r;
294*00b67f09SDavid van Moolenbroek 	gss_buffer_desc gssbuffer;
295*00b67f09SDavid van Moolenbroek 	isc_result_t result;
296*00b67f09SDavid van Moolenbroek 
297*00b67f09SDavid van Moolenbroek 	len = strlen(keystr);
298*00b67f09SDavid van Moolenbroek 	if ((len % 4) != 0U)
299*00b67f09SDavid van Moolenbroek 		return (ISC_R_BADBASE64);
300*00b67f09SDavid van Moolenbroek 
301*00b67f09SDavid van Moolenbroek 	len = (len / 4) * 3;
302*00b67f09SDavid van Moolenbroek 
303*00b67f09SDavid van Moolenbroek 	result = isc_buffer_allocate(key->mctx, &b, len);
304*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
305*00b67f09SDavid van Moolenbroek 		return (result);
306*00b67f09SDavid van Moolenbroek 
307*00b67f09SDavid van Moolenbroek 	result = isc_base64_decodestring(keystr, b);
308*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
309*00b67f09SDavid van Moolenbroek 		isc_buffer_free(&b);
310*00b67f09SDavid van Moolenbroek 		return (result);
311*00b67f09SDavid van Moolenbroek 	}
312*00b67f09SDavid van Moolenbroek 
313*00b67f09SDavid van Moolenbroek 	isc_buffer_remainingregion(b, &r);
314*00b67f09SDavid van Moolenbroek 	REGION_TO_GBUFFER(r, gssbuffer);
315*00b67f09SDavid van Moolenbroek 	major = gss_import_sec_context(&minor, &gssbuffer,
316*00b67f09SDavid van Moolenbroek 				       &key->keydata.gssctx);
317*00b67f09SDavid van Moolenbroek 	if (major != GSS_S_COMPLETE) {
318*00b67f09SDavid van Moolenbroek 		isc_buffer_free(&b);
319*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
320*00b67f09SDavid van Moolenbroek 	}
321*00b67f09SDavid van Moolenbroek 
322*00b67f09SDavid van Moolenbroek 	isc_buffer_free(&b);
323*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
324*00b67f09SDavid van Moolenbroek }
325*00b67f09SDavid van Moolenbroek 
326*00b67f09SDavid van Moolenbroek static isc_result_t
gssapi_dump(dst_key_t * key,isc_mem_t * mctx,char ** buffer,int * length)327*00b67f09SDavid van Moolenbroek gssapi_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
328*00b67f09SDavid van Moolenbroek 	OM_uint32 major, minor;
329*00b67f09SDavid van Moolenbroek 	gss_buffer_desc gssbuffer;
330*00b67f09SDavid van Moolenbroek 	size_t len;
331*00b67f09SDavid van Moolenbroek 	char *buf;
332*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
333*00b67f09SDavid van Moolenbroek 	isc_region_t r;
334*00b67f09SDavid van Moolenbroek 	isc_result_t result;
335*00b67f09SDavid van Moolenbroek 
336*00b67f09SDavid van Moolenbroek 	major = gss_export_sec_context(&minor, &key->keydata.gssctx,
337*00b67f09SDavid van Moolenbroek 				       &gssbuffer);
338*00b67f09SDavid van Moolenbroek 	if (major != GSS_S_COMPLETE) {
339*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "gss_export_sec_context -> %d, %d\n",
340*00b67f09SDavid van Moolenbroek 			major, minor);
341*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
342*00b67f09SDavid van Moolenbroek 	}
343*00b67f09SDavid van Moolenbroek 	if (gssbuffer.length == 0U)
344*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
345*00b67f09SDavid van Moolenbroek 	len = ((gssbuffer.length + 2)/3) * 4;
346*00b67f09SDavid van Moolenbroek 	buf = isc_mem_get(mctx, len);
347*00b67f09SDavid van Moolenbroek 	if (buf == NULL) {
348*00b67f09SDavid van Moolenbroek 		gss_release_buffer(&minor, &gssbuffer);
349*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
350*00b67f09SDavid van Moolenbroek 	}
351*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&b, buf, (unsigned int)len);
352*00b67f09SDavid van Moolenbroek 	GBUFFER_TO_REGION(gssbuffer, r);
353*00b67f09SDavid van Moolenbroek 	result = isc_base64_totext(&r, 0, "", &b);
354*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
355*00b67f09SDavid van Moolenbroek 	gss_release_buffer(&minor, &gssbuffer);
356*00b67f09SDavid van Moolenbroek 	*buffer = buf;
357*00b67f09SDavid van Moolenbroek 	*length = (int)len;
358*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
359*00b67f09SDavid van Moolenbroek }
360*00b67f09SDavid van Moolenbroek 
361*00b67f09SDavid van Moolenbroek static dst_func_t gssapi_functions = {
362*00b67f09SDavid van Moolenbroek 	gssapi_create_signverify_ctx,
363*00b67f09SDavid van Moolenbroek 	NULL, /*%< createctx2 */
364*00b67f09SDavid van Moolenbroek 	gssapi_destroy_signverify_ctx,
365*00b67f09SDavid van Moolenbroek 	gssapi_adddata,
366*00b67f09SDavid van Moolenbroek 	gssapi_sign,
367*00b67f09SDavid van Moolenbroek 	gssapi_verify,
368*00b67f09SDavid van Moolenbroek 	NULL, /*%< verify2 */
369*00b67f09SDavid van Moolenbroek 	NULL, /*%< computesecret */
370*00b67f09SDavid van Moolenbroek 	gssapi_compare,
371*00b67f09SDavid van Moolenbroek 	NULL, /*%< paramcompare */
372*00b67f09SDavid van Moolenbroek 	gssapi_generate,
373*00b67f09SDavid van Moolenbroek 	gssapi_isprivate,
374*00b67f09SDavid van Moolenbroek 	gssapi_destroy,
375*00b67f09SDavid van Moolenbroek 	NULL, /*%< todns */
376*00b67f09SDavid van Moolenbroek 	NULL, /*%< fromdns */
377*00b67f09SDavid van Moolenbroek 	NULL, /*%< tofile */
378*00b67f09SDavid van Moolenbroek 	NULL, /*%< parse */
379*00b67f09SDavid van Moolenbroek 	NULL, /*%< cleanup */
380*00b67f09SDavid van Moolenbroek 	NULL,  /*%< fromlabel */
381*00b67f09SDavid van Moolenbroek 	gssapi_dump,
382*00b67f09SDavid van Moolenbroek 	gssapi_restore,
383*00b67f09SDavid van Moolenbroek };
384*00b67f09SDavid van Moolenbroek 
385*00b67f09SDavid van Moolenbroek isc_result_t
dst__gssapi_init(dst_func_t ** funcp)386*00b67f09SDavid van Moolenbroek dst__gssapi_init(dst_func_t **funcp) {
387*00b67f09SDavid van Moolenbroek 	REQUIRE(funcp != NULL);
388*00b67f09SDavid van Moolenbroek 	if (*funcp == NULL)
389*00b67f09SDavid van Moolenbroek 		*funcp = &gssapi_functions;
390*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
391*00b67f09SDavid van Moolenbroek }
392*00b67f09SDavid van Moolenbroek 
393*00b67f09SDavid van Moolenbroek #else
394*00b67f09SDavid van Moolenbroek int  gssapi_link_unneeded = 1;
395*00b67f09SDavid van Moolenbroek #endif
396*00b67f09SDavid van Moolenbroek 
397*00b67f09SDavid van Moolenbroek /*! \file */
398