xref: /freebsd/crypto/heimdal/lib/gssapi/mech/gss_krb5.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1*ae771770SStanislav Sedov /*-
2*ae771770SStanislav Sedov  * Copyright (c) 2005 Doug Rabson
3*ae771770SStanislav Sedov  * All rights reserved.
4*ae771770SStanislav Sedov  *
5*ae771770SStanislav Sedov  * Redistribution and use in source and binary forms, with or without
6*ae771770SStanislav Sedov  * modification, are permitted provided that the following conditions
7*ae771770SStanislav Sedov  * are met:
8*ae771770SStanislav Sedov  * 1. Redistributions of source code must retain the above copyright
9*ae771770SStanislav Sedov  *    notice, this list of conditions and the following disclaimer.
10*ae771770SStanislav Sedov  * 2. Redistributions in binary form must reproduce the above copyright
11*ae771770SStanislav Sedov  *    notice, this list of conditions and the following disclaimer in the
12*ae771770SStanislav Sedov  *    documentation and/or other materials provided with the distribution.
13*ae771770SStanislav Sedov  *
14*ae771770SStanislav Sedov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*ae771770SStanislav Sedov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*ae771770SStanislav Sedov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*ae771770SStanislav Sedov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*ae771770SStanislav Sedov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*ae771770SStanislav Sedov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*ae771770SStanislav Sedov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*ae771770SStanislav Sedov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*ae771770SStanislav Sedov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*ae771770SStanislav Sedov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*ae771770SStanislav Sedov  * SUCH DAMAGE.
25*ae771770SStanislav Sedov  *
26*ae771770SStanislav Sedov  *	$FreeBSD: src/lib/libgssapi/gss_krb5.c,v 1.1 2005/12/29 14:40:20 dfr Exp $
27*ae771770SStanislav Sedov  */
28*ae771770SStanislav Sedov 
29*ae771770SStanislav Sedov #include "mech_locl.h"
30*ae771770SStanislav Sedov 
31*ae771770SStanislav Sedov #include <krb5.h>
32*ae771770SStanislav Sedov #include <roken.h>
33*ae771770SStanislav Sedov 
34*ae771770SStanislav Sedov 
35*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_krb5_copy_ccache(OM_uint32 * minor_status,gss_cred_id_t cred,krb5_ccache out)36*ae771770SStanislav Sedov gss_krb5_copy_ccache(OM_uint32 *minor_status,
37*ae771770SStanislav Sedov 		     gss_cred_id_t cred,
38*ae771770SStanislav Sedov 		     krb5_ccache out)
39*ae771770SStanislav Sedov {
40*ae771770SStanislav Sedov     gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
41*ae771770SStanislav Sedov     krb5_context context;
42*ae771770SStanislav Sedov     krb5_error_code kret;
43*ae771770SStanislav Sedov     krb5_ccache id;
44*ae771770SStanislav Sedov     OM_uint32 ret;
45*ae771770SStanislav Sedov     char *str = NULL;
46*ae771770SStanislav Sedov 
47*ae771770SStanislav Sedov     ret = gss_inquire_cred_by_oid(minor_status,
48*ae771770SStanislav Sedov 				  cred,
49*ae771770SStanislav Sedov 				  GSS_KRB5_COPY_CCACHE_X,
50*ae771770SStanislav Sedov 				  &data_set);
51*ae771770SStanislav Sedov     if (ret)
52*ae771770SStanislav Sedov 	return ret;
53*ae771770SStanislav Sedov 
54*ae771770SStanislav Sedov     if (data_set == GSS_C_NO_BUFFER_SET || data_set->count < 1) {
55*ae771770SStanislav Sedov 	gss_release_buffer_set(minor_status, &data_set);
56*ae771770SStanislav Sedov 	*minor_status = EINVAL;
57*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
58*ae771770SStanislav Sedov     }
59*ae771770SStanislav Sedov 
60*ae771770SStanislav Sedov     kret = krb5_init_context(&context);
61*ae771770SStanislav Sedov     if (kret) {
62*ae771770SStanislav Sedov 	*minor_status = kret;
63*ae771770SStanislav Sedov 	gss_release_buffer_set(minor_status, &data_set);
64*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
65*ae771770SStanislav Sedov     }
66*ae771770SStanislav Sedov 
67*ae771770SStanislav Sedov     kret = asprintf(&str, "%.*s", (int)data_set->elements[0].length,
68*ae771770SStanislav Sedov 		    (char *)data_set->elements[0].value);
69*ae771770SStanislav Sedov     gss_release_buffer_set(minor_status, &data_set);
70*ae771770SStanislav Sedov     if (kret < 0 || str == NULL) {
71*ae771770SStanislav Sedov 	*minor_status = ENOMEM;
72*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
73*ae771770SStanislav Sedov     }
74*ae771770SStanislav Sedov 
75*ae771770SStanislav Sedov     kret = krb5_cc_resolve(context, str, &id);
76*ae771770SStanislav Sedov     free(str);
77*ae771770SStanislav Sedov     if (kret) {
78*ae771770SStanislav Sedov 	*minor_status = kret;
79*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
80*ae771770SStanislav Sedov     }
81*ae771770SStanislav Sedov 
82*ae771770SStanislav Sedov     kret = krb5_cc_copy_cache(context, id, out);
83*ae771770SStanislav Sedov     krb5_cc_close(context, id);
84*ae771770SStanislav Sedov     krb5_free_context(context);
85*ae771770SStanislav Sedov     if (kret) {
86*ae771770SStanislav Sedov 	*minor_status = kret;
87*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
88*ae771770SStanislav Sedov     }
89*ae771770SStanislav Sedov 
90*ae771770SStanislav Sedov     return ret;
91*ae771770SStanislav Sedov }
92*ae771770SStanislav Sedov 
93*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_krb5_import_cred(OM_uint32 * minor_status,krb5_ccache id,krb5_principal keytab_principal,krb5_keytab keytab,gss_cred_id_t * cred)94*ae771770SStanislav Sedov gss_krb5_import_cred(OM_uint32 *minor_status,
95*ae771770SStanislav Sedov 		     krb5_ccache id,
96*ae771770SStanislav Sedov 		     krb5_principal keytab_principal,
97*ae771770SStanislav Sedov 		     krb5_keytab keytab,
98*ae771770SStanislav Sedov 		     gss_cred_id_t *cred)
99*ae771770SStanislav Sedov {
100*ae771770SStanislav Sedov     gss_buffer_desc buffer;
101*ae771770SStanislav Sedov     OM_uint32 major_status;
102*ae771770SStanislav Sedov     krb5_context context;
103*ae771770SStanislav Sedov     krb5_error_code ret;
104*ae771770SStanislav Sedov     krb5_storage *sp;
105*ae771770SStanislav Sedov     krb5_data data;
106*ae771770SStanislav Sedov     char *str;
107*ae771770SStanislav Sedov 
108*ae771770SStanislav Sedov     *cred = GSS_C_NO_CREDENTIAL;
109*ae771770SStanislav Sedov 
110*ae771770SStanislav Sedov     ret = krb5_init_context(&context);
111*ae771770SStanislav Sedov     if (ret) {
112*ae771770SStanislav Sedov 	*minor_status = ret;
113*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
114*ae771770SStanislav Sedov     }
115*ae771770SStanislav Sedov 
116*ae771770SStanislav Sedov     sp = krb5_storage_emem();
117*ae771770SStanislav Sedov     if (sp == NULL) {
118*ae771770SStanislav Sedov 	*minor_status = ENOMEM;
119*ae771770SStanislav Sedov 	major_status = GSS_S_FAILURE;
120*ae771770SStanislav Sedov 	goto out;
121*ae771770SStanislav Sedov     }
122*ae771770SStanislav Sedov 
123*ae771770SStanislav Sedov     if (id) {
124*ae771770SStanislav Sedov 	ret = krb5_cc_get_full_name(context, id, &str);
125*ae771770SStanislav Sedov 	if (ret == 0) {
126*ae771770SStanislav Sedov 	    ret = krb5_store_string(sp, str);
127*ae771770SStanislav Sedov 	    free(str);
128*ae771770SStanislav Sedov 	}
129*ae771770SStanislav Sedov     } else
130*ae771770SStanislav Sedov 	ret = krb5_store_string(sp, "");
131*ae771770SStanislav Sedov     if (ret) {
132*ae771770SStanislav Sedov 	*minor_status = ret;
133*ae771770SStanislav Sedov 	major_status = GSS_S_FAILURE;
134*ae771770SStanislav Sedov 	goto out;
135*ae771770SStanislav Sedov     }
136*ae771770SStanislav Sedov 
137*ae771770SStanislav Sedov     if (keytab_principal) {
138*ae771770SStanislav Sedov 	ret = krb5_unparse_name(context, keytab_principal, &str);
139*ae771770SStanislav Sedov 	if (ret == 0) {
140*ae771770SStanislav Sedov 	    ret = krb5_store_string(sp, str);
141*ae771770SStanislav Sedov 	    free(str);
142*ae771770SStanislav Sedov 	}
143*ae771770SStanislav Sedov     } else
144*ae771770SStanislav Sedov 	krb5_store_string(sp, "");
145*ae771770SStanislav Sedov     if (ret) {
146*ae771770SStanislav Sedov 	*minor_status = ret;
147*ae771770SStanislav Sedov 	major_status = GSS_S_FAILURE;
148*ae771770SStanislav Sedov 	goto out;
149*ae771770SStanislav Sedov     }
150*ae771770SStanislav Sedov 
151*ae771770SStanislav Sedov 
152*ae771770SStanislav Sedov     if (keytab) {
153*ae771770SStanislav Sedov 	ret = krb5_kt_get_full_name(context, keytab, &str);
154*ae771770SStanislav Sedov 	if (ret == 0) {
155*ae771770SStanislav Sedov 	    ret = krb5_store_string(sp, str);
156*ae771770SStanislav Sedov 	    free(str);
157*ae771770SStanislav Sedov 	}
158*ae771770SStanislav Sedov     } else
159*ae771770SStanislav Sedov 	krb5_store_string(sp, "");
160*ae771770SStanislav Sedov     if (ret) {
161*ae771770SStanislav Sedov 	*minor_status = ret;
162*ae771770SStanislav Sedov 	major_status = GSS_S_FAILURE;
163*ae771770SStanislav Sedov 	goto out;
164*ae771770SStanislav Sedov     }
165*ae771770SStanislav Sedov 
166*ae771770SStanislav Sedov     ret = krb5_storage_to_data(sp, &data);
167*ae771770SStanislav Sedov     if (ret) {
168*ae771770SStanislav Sedov 	*minor_status = ret;
169*ae771770SStanislav Sedov 	major_status = GSS_S_FAILURE;
170*ae771770SStanislav Sedov 	goto out;
171*ae771770SStanislav Sedov     }
172*ae771770SStanislav Sedov 
173*ae771770SStanislav Sedov     buffer.value = data.data;
174*ae771770SStanislav Sedov     buffer.length = data.length;
175*ae771770SStanislav Sedov 
176*ae771770SStanislav Sedov     major_status = gss_set_cred_option(minor_status,
177*ae771770SStanislav Sedov 				       cred,
178*ae771770SStanislav Sedov 				       GSS_KRB5_IMPORT_CRED_X,
179*ae771770SStanislav Sedov 				       &buffer);
180*ae771770SStanislav Sedov     krb5_data_free(&data);
181*ae771770SStanislav Sedov out:
182*ae771770SStanislav Sedov     if (sp)
183*ae771770SStanislav Sedov 	krb5_storage_free(sp);
184*ae771770SStanislav Sedov     krb5_free_context(context);
185*ae771770SStanislav Sedov     return major_status;
186*ae771770SStanislav Sedov }
187*ae771770SStanislav Sedov 
188*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_register_acceptor_identity(const char * identity)189*ae771770SStanislav Sedov gsskrb5_register_acceptor_identity(const char *identity)
190*ae771770SStanislav Sedov {
191*ae771770SStanislav Sedov 	gssapi_mech_interface m;
192*ae771770SStanislav Sedov 	gss_buffer_desc buffer;
193*ae771770SStanislav Sedov 	OM_uint32 junk;
194*ae771770SStanislav Sedov 
195*ae771770SStanislav Sedov 	_gss_load_mech();
196*ae771770SStanislav Sedov 
197*ae771770SStanislav Sedov 	buffer.value = rk_UNCONST(identity);
198*ae771770SStanislav Sedov 	buffer.length = strlen(identity);
199*ae771770SStanislav Sedov 
200*ae771770SStanislav Sedov 	m = __gss_get_mechanism(GSS_KRB5_MECHANISM);
201*ae771770SStanislav Sedov 	if (m == NULL || m->gm_set_sec_context_option == NULL)
202*ae771770SStanislav Sedov 	    return GSS_S_FAILURE;
203*ae771770SStanislav Sedov 
204*ae771770SStanislav Sedov 	return m->gm_set_sec_context_option(&junk, NULL,
205*ae771770SStanislav Sedov 	        GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X, &buffer);
206*ae771770SStanislav Sedov }
207*ae771770SStanislav Sedov 
208*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
krb5_gss_register_acceptor_identity(const char * identity)209*ae771770SStanislav Sedov krb5_gss_register_acceptor_identity(const char *identity)
210*ae771770SStanislav Sedov {
211*ae771770SStanislav Sedov     return gsskrb5_register_acceptor_identity(identity);
212*ae771770SStanislav Sedov }
213*ae771770SStanislav Sedov 
214*ae771770SStanislav Sedov 
215*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_set_dns_canonicalize(int flag)216*ae771770SStanislav Sedov gsskrb5_set_dns_canonicalize(int flag)
217*ae771770SStanislav Sedov {
218*ae771770SStanislav Sedov         struct _gss_mech_switch	*m;
219*ae771770SStanislav Sedov 	gss_buffer_desc buffer;
220*ae771770SStanislav Sedov 	OM_uint32 junk;
221*ae771770SStanislav Sedov 	char b = (flag != 0);
222*ae771770SStanislav Sedov 
223*ae771770SStanislav Sedov 	_gss_load_mech();
224*ae771770SStanislav Sedov 
225*ae771770SStanislav Sedov 	buffer.value = &b;
226*ae771770SStanislav Sedov 	buffer.length = sizeof(b);
227*ae771770SStanislav Sedov 
228*ae771770SStanislav Sedov 	HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
229*ae771770SStanislav Sedov 		if (m->gm_mech.gm_set_sec_context_option == NULL)
230*ae771770SStanislav Sedov 			continue;
231*ae771770SStanislav Sedov 		m->gm_mech.gm_set_sec_context_option(&junk, NULL,
232*ae771770SStanislav Sedov 		    GSS_KRB5_SET_DNS_CANONICALIZE_X, &buffer);
233*ae771770SStanislav Sedov 	}
234*ae771770SStanislav Sedov 
235*ae771770SStanislav Sedov 	return (GSS_S_COMPLETE);
236*ae771770SStanislav Sedov }
237*ae771770SStanislav Sedov 
238*ae771770SStanislav Sedov 
239*ae771770SStanislav Sedov 
240*ae771770SStanislav Sedov static krb5_error_code
set_key(krb5_keyblock * keyblock,gss_krb5_lucid_key_t * key)241*ae771770SStanislav Sedov set_key(krb5_keyblock *keyblock, gss_krb5_lucid_key_t *key)
242*ae771770SStanislav Sedov {
243*ae771770SStanislav Sedov     key->type = keyblock->keytype;
244*ae771770SStanislav Sedov     key->length = keyblock->keyvalue.length;
245*ae771770SStanislav Sedov     key->data = malloc(key->length);
246*ae771770SStanislav Sedov     if (key->data == NULL && key->length != 0)
247*ae771770SStanislav Sedov 	return ENOMEM;
248*ae771770SStanislav Sedov     memcpy(key->data, keyblock->keyvalue.data, key->length);
249*ae771770SStanislav Sedov     return 0;
250*ae771770SStanislav Sedov }
251*ae771770SStanislav Sedov 
252*ae771770SStanislav Sedov static void
free_key(gss_krb5_lucid_key_t * key)253*ae771770SStanislav Sedov free_key(gss_krb5_lucid_key_t *key)
254*ae771770SStanislav Sedov {
255*ae771770SStanislav Sedov     memset(key->data, 0, key->length);
256*ae771770SStanislav Sedov     free(key->data);
257*ae771770SStanislav Sedov     memset(key, 0, sizeof(*key));
258*ae771770SStanislav Sedov }
259*ae771770SStanislav Sedov 
260*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_krb5_export_lucid_sec_context(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,OM_uint32 version,void ** rctx)261*ae771770SStanislav Sedov gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
262*ae771770SStanislav Sedov 				  gss_ctx_id_t *context_handle,
263*ae771770SStanislav Sedov 				  OM_uint32 version,
264*ae771770SStanislav Sedov 				  void **rctx)
265*ae771770SStanislav Sedov {
266*ae771770SStanislav Sedov     krb5_context context = NULL;
267*ae771770SStanislav Sedov     krb5_error_code ret;
268*ae771770SStanislav Sedov     gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
269*ae771770SStanislav Sedov     OM_uint32 major_status;
270*ae771770SStanislav Sedov     gss_krb5_lucid_context_v1_t *ctx = NULL;
271*ae771770SStanislav Sedov     krb5_storage *sp = NULL;
272*ae771770SStanislav Sedov     uint32_t num;
273*ae771770SStanislav Sedov 
274*ae771770SStanislav Sedov     if (context_handle == NULL
275*ae771770SStanislav Sedov 	|| *context_handle == GSS_C_NO_CONTEXT
276*ae771770SStanislav Sedov 	|| version != 1)
277*ae771770SStanislav Sedov     {
278*ae771770SStanislav Sedov 	*minor_status = EINVAL;
279*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
280*ae771770SStanislav Sedov     }
281*ae771770SStanislav Sedov 
282*ae771770SStanislav Sedov     major_status =
283*ae771770SStanislav Sedov 	gss_inquire_sec_context_by_oid (minor_status,
284*ae771770SStanislav Sedov 					*context_handle,
285*ae771770SStanislav Sedov 					GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X,
286*ae771770SStanislav Sedov 					&data_set);
287*ae771770SStanislav Sedov     if (major_status)
288*ae771770SStanislav Sedov 	return major_status;
289*ae771770SStanislav Sedov 
290*ae771770SStanislav Sedov     if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
291*ae771770SStanislav Sedov 	gss_release_buffer_set(minor_status, &data_set);
292*ae771770SStanislav Sedov 	*minor_status = EINVAL;
293*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
294*ae771770SStanislav Sedov     }
295*ae771770SStanislav Sedov 
296*ae771770SStanislav Sedov     ret = krb5_init_context(&context);
297*ae771770SStanislav Sedov     if (ret)
298*ae771770SStanislav Sedov 	goto out;
299*ae771770SStanislav Sedov 
300*ae771770SStanislav Sedov     ctx = calloc(1, sizeof(*ctx));
301*ae771770SStanislav Sedov     if (ctx == NULL) {
302*ae771770SStanislav Sedov 	ret = ENOMEM;
303*ae771770SStanislav Sedov 	goto out;
304*ae771770SStanislav Sedov     }
305*ae771770SStanislav Sedov 
306*ae771770SStanislav Sedov     sp = krb5_storage_from_mem(data_set->elements[0].value,
307*ae771770SStanislav Sedov 			       data_set->elements[0].length);
308*ae771770SStanislav Sedov     if (sp == NULL) {
309*ae771770SStanislav Sedov 	ret = ENOMEM;
310*ae771770SStanislav Sedov 	goto out;
311*ae771770SStanislav Sedov     }
312*ae771770SStanislav Sedov 
313*ae771770SStanislav Sedov     ret = krb5_ret_uint32(sp, &num);
314*ae771770SStanislav Sedov     if (ret) goto out;
315*ae771770SStanislav Sedov     if (num != 1) {
316*ae771770SStanislav Sedov 	ret = EINVAL;
317*ae771770SStanislav Sedov 	goto out;
318*ae771770SStanislav Sedov     }
319*ae771770SStanislav Sedov     ctx->version = 1;
320*ae771770SStanislav Sedov     /* initiator */
321*ae771770SStanislav Sedov     ret = krb5_ret_uint32(sp, &ctx->initiate);
322*ae771770SStanislav Sedov     if (ret) goto out;
323*ae771770SStanislav Sedov     /* endtime */
324*ae771770SStanislav Sedov     ret = krb5_ret_uint32(sp, &ctx->endtime);
325*ae771770SStanislav Sedov     if (ret) goto out;
326*ae771770SStanislav Sedov     /* send_seq */
327*ae771770SStanislav Sedov     ret = krb5_ret_uint32(sp, &num);
328*ae771770SStanislav Sedov     if (ret) goto out;
329*ae771770SStanislav Sedov     ctx->send_seq = ((uint64_t)num) << 32;
330*ae771770SStanislav Sedov     ret = krb5_ret_uint32(sp, &num);
331*ae771770SStanislav Sedov     if (ret) goto out;
332*ae771770SStanislav Sedov     ctx->send_seq |= num;
333*ae771770SStanislav Sedov     /* recv_seq */
334*ae771770SStanislav Sedov     ret = krb5_ret_uint32(sp, &num);
335*ae771770SStanislav Sedov     if (ret) goto out;
336*ae771770SStanislav Sedov     ctx->recv_seq = ((uint64_t)num) << 32;
337*ae771770SStanislav Sedov     ret = krb5_ret_uint32(sp, &num);
338*ae771770SStanislav Sedov     if (ret) goto out;
339*ae771770SStanislav Sedov     ctx->recv_seq |= num;
340*ae771770SStanislav Sedov     /* protocol */
341*ae771770SStanislav Sedov     ret = krb5_ret_uint32(sp, &ctx->protocol);
342*ae771770SStanislav Sedov     if (ret) goto out;
343*ae771770SStanislav Sedov     if (ctx->protocol == 0) {
344*ae771770SStanislav Sedov 	krb5_keyblock key;
345*ae771770SStanislav Sedov 
346*ae771770SStanislav Sedov 	/* sign_alg */
347*ae771770SStanislav Sedov 	ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.sign_alg);
348*ae771770SStanislav Sedov 	if (ret) goto out;
349*ae771770SStanislav Sedov 	/* seal_alg */
350*ae771770SStanislav Sedov 	ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.seal_alg);
351*ae771770SStanislav Sedov 	if (ret) goto out;
352*ae771770SStanislav Sedov 	/* ctx_key */
353*ae771770SStanislav Sedov 	ret = krb5_ret_keyblock(sp, &key);
354*ae771770SStanislav Sedov 	if (ret) goto out;
355*ae771770SStanislav Sedov 	ret = set_key(&key, &ctx->rfc1964_kd.ctx_key);
356*ae771770SStanislav Sedov 	krb5_free_keyblock_contents(context, &key);
357*ae771770SStanislav Sedov 	if (ret) goto out;
358*ae771770SStanislav Sedov     } else if (ctx->protocol == 1) {
359*ae771770SStanislav Sedov 	krb5_keyblock key;
360*ae771770SStanislav Sedov 
361*ae771770SStanislav Sedov 	/* acceptor_subkey */
362*ae771770SStanislav Sedov 	ret = krb5_ret_uint32(sp, &ctx->cfx_kd.have_acceptor_subkey);
363*ae771770SStanislav Sedov 	if (ret) goto out;
364*ae771770SStanislav Sedov 	/* ctx_key */
365*ae771770SStanislav Sedov 	ret = krb5_ret_keyblock(sp, &key);
366*ae771770SStanislav Sedov 	if (ret) goto out;
367*ae771770SStanislav Sedov 	ret = set_key(&key, &ctx->cfx_kd.ctx_key);
368*ae771770SStanislav Sedov 	krb5_free_keyblock_contents(context, &key);
369*ae771770SStanislav Sedov 	if (ret) goto out;
370*ae771770SStanislav Sedov 	/* acceptor_subkey */
371*ae771770SStanislav Sedov 	if (ctx->cfx_kd.have_acceptor_subkey) {
372*ae771770SStanislav Sedov 	    ret = krb5_ret_keyblock(sp, &key);
373*ae771770SStanislav Sedov 	    if (ret) goto out;
374*ae771770SStanislav Sedov 	    ret = set_key(&key, &ctx->cfx_kd.acceptor_subkey);
375*ae771770SStanislav Sedov 	    krb5_free_keyblock_contents(context, &key);
376*ae771770SStanislav Sedov 	    if (ret) goto out;
377*ae771770SStanislav Sedov 	}
378*ae771770SStanislav Sedov     } else {
379*ae771770SStanislav Sedov 	ret = EINVAL;
380*ae771770SStanislav Sedov 	goto out;
381*ae771770SStanislav Sedov     }
382*ae771770SStanislav Sedov 
383*ae771770SStanislav Sedov     *rctx = ctx;
384*ae771770SStanislav Sedov 
385*ae771770SStanislav Sedov out:
386*ae771770SStanislav Sedov     gss_release_buffer_set(minor_status, &data_set);
387*ae771770SStanislav Sedov     if (sp)
388*ae771770SStanislav Sedov 	krb5_storage_free(sp);
389*ae771770SStanislav Sedov     if (context)
390*ae771770SStanislav Sedov 	krb5_free_context(context);
391*ae771770SStanislav Sedov 
392*ae771770SStanislav Sedov     if (ret) {
393*ae771770SStanislav Sedov 	if (ctx)
394*ae771770SStanislav Sedov 	    gss_krb5_free_lucid_sec_context(NULL, ctx);
395*ae771770SStanislav Sedov 
396*ae771770SStanislav Sedov 	*minor_status = ret;
397*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
398*ae771770SStanislav Sedov     }
399*ae771770SStanislav Sedov     *minor_status = 0;
400*ae771770SStanislav Sedov     return GSS_S_COMPLETE;
401*ae771770SStanislav Sedov }
402*ae771770SStanislav Sedov 
403*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_krb5_free_lucid_sec_context(OM_uint32 * minor_status,void * c)404*ae771770SStanislav Sedov gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *c)
405*ae771770SStanislav Sedov {
406*ae771770SStanislav Sedov     gss_krb5_lucid_context_v1_t *ctx = c;
407*ae771770SStanislav Sedov 
408*ae771770SStanislav Sedov     if (ctx->version != 1) {
409*ae771770SStanislav Sedov 	if (minor_status)
410*ae771770SStanislav Sedov 	    *minor_status = 0;
411*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
412*ae771770SStanislav Sedov     }
413*ae771770SStanislav Sedov 
414*ae771770SStanislav Sedov     if (ctx->protocol == 0) {
415*ae771770SStanislav Sedov 	free_key(&ctx->rfc1964_kd.ctx_key);
416*ae771770SStanislav Sedov     } else if (ctx->protocol == 1) {
417*ae771770SStanislav Sedov 	free_key(&ctx->cfx_kd.ctx_key);
418*ae771770SStanislav Sedov 	if (ctx->cfx_kd.have_acceptor_subkey)
419*ae771770SStanislav Sedov 	    free_key(&ctx->cfx_kd.acceptor_subkey);
420*ae771770SStanislav Sedov     }
421*ae771770SStanislav Sedov     free(ctx);
422*ae771770SStanislav Sedov     if (minor_status)
423*ae771770SStanislav Sedov 	*minor_status = 0;
424*ae771770SStanislav Sedov     return GSS_S_COMPLETE;
425*ae771770SStanislav Sedov }
426*ae771770SStanislav Sedov 
427*ae771770SStanislav Sedov /*
428*ae771770SStanislav Sedov  *
429*ae771770SStanislav Sedov  */
430*ae771770SStanislav Sedov 
431*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_krb5_set_allowable_enctypes(OM_uint32 * minor_status,gss_cred_id_t cred,OM_uint32 num_enctypes,int32_t * enctypes)432*ae771770SStanislav Sedov gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
433*ae771770SStanislav Sedov 				gss_cred_id_t cred,
434*ae771770SStanislav Sedov 				OM_uint32 num_enctypes,
435*ae771770SStanislav Sedov 				int32_t *enctypes)
436*ae771770SStanislav Sedov {
437*ae771770SStanislav Sedov     krb5_error_code ret;
438*ae771770SStanislav Sedov     OM_uint32 maj_status;
439*ae771770SStanislav Sedov     gss_buffer_desc buffer;
440*ae771770SStanislav Sedov     krb5_storage *sp;
441*ae771770SStanislav Sedov     krb5_data data;
442*ae771770SStanislav Sedov     size_t i;
443*ae771770SStanislav Sedov 
444*ae771770SStanislav Sedov     sp = krb5_storage_emem();
445*ae771770SStanislav Sedov     if (sp == NULL) {
446*ae771770SStanislav Sedov 	*minor_status = ENOMEM;
447*ae771770SStanislav Sedov 	maj_status = GSS_S_FAILURE;
448*ae771770SStanislav Sedov 	goto out;
449*ae771770SStanislav Sedov     }
450*ae771770SStanislav Sedov 
451*ae771770SStanislav Sedov     for (i = 0; i < num_enctypes; i++) {
452*ae771770SStanislav Sedov 	ret = krb5_store_int32(sp, enctypes[i]);
453*ae771770SStanislav Sedov 	if (ret) {
454*ae771770SStanislav Sedov 	    *minor_status = ret;
455*ae771770SStanislav Sedov 	    maj_status = GSS_S_FAILURE;
456*ae771770SStanislav Sedov 	    goto out;
457*ae771770SStanislav Sedov 	}
458*ae771770SStanislav Sedov     }
459*ae771770SStanislav Sedov 
460*ae771770SStanislav Sedov     ret = krb5_storage_to_data(sp, &data);
461*ae771770SStanislav Sedov     if (ret) {
462*ae771770SStanislav Sedov 	*minor_status = ret;
463*ae771770SStanislav Sedov 	maj_status = GSS_S_FAILURE;
464*ae771770SStanislav Sedov 	goto out;
465*ae771770SStanislav Sedov     }
466*ae771770SStanislav Sedov 
467*ae771770SStanislav Sedov     buffer.value = data.data;
468*ae771770SStanislav Sedov     buffer.length = data.length;
469*ae771770SStanislav Sedov 
470*ae771770SStanislav Sedov     maj_status = gss_set_cred_option(minor_status,
471*ae771770SStanislav Sedov 				     &cred,
472*ae771770SStanislav Sedov 				     GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X,
473*ae771770SStanislav Sedov 				     &buffer);
474*ae771770SStanislav Sedov     krb5_data_free(&data);
475*ae771770SStanislav Sedov out:
476*ae771770SStanislav Sedov     if (sp)
477*ae771770SStanislav Sedov 	krb5_storage_free(sp);
478*ae771770SStanislav Sedov     return maj_status;
479*ae771770SStanislav Sedov }
480*ae771770SStanislav Sedov 
481*ae771770SStanislav Sedov /*
482*ae771770SStanislav Sedov  *
483*ae771770SStanislav Sedov  */
484*ae771770SStanislav Sedov 
485*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc * c)486*ae771770SStanislav Sedov gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c)
487*ae771770SStanislav Sedov {
488*ae771770SStanislav Sedov     struct _gss_mech_switch *m;
489*ae771770SStanislav Sedov     gss_buffer_desc buffer;
490*ae771770SStanislav Sedov     OM_uint32 junk;
491*ae771770SStanislav Sedov 
492*ae771770SStanislav Sedov     _gss_load_mech();
493*ae771770SStanislav Sedov 
494*ae771770SStanislav Sedov     if (c) {
495*ae771770SStanislav Sedov 	buffer.value = c;
496*ae771770SStanislav Sedov 	buffer.length = sizeof(*c);
497*ae771770SStanislav Sedov     } else {
498*ae771770SStanislav Sedov 	buffer.value = NULL;
499*ae771770SStanislav Sedov 	buffer.length = 0;
500*ae771770SStanislav Sedov     }
501*ae771770SStanislav Sedov 
502*ae771770SStanislav Sedov     HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
503*ae771770SStanislav Sedov 	if (m->gm_mech.gm_set_sec_context_option == NULL)
504*ae771770SStanislav Sedov 	    continue;
505*ae771770SStanislav Sedov 	m->gm_mech.gm_set_sec_context_option(&junk, NULL,
506*ae771770SStanislav Sedov 	    GSS_KRB5_SEND_TO_KDC_X, &buffer);
507*ae771770SStanislav Sedov     }
508*ae771770SStanislav Sedov 
509*ae771770SStanislav Sedov     return (GSS_S_COMPLETE);
510*ae771770SStanislav Sedov }
511*ae771770SStanislav Sedov 
512*ae771770SStanislav Sedov /*
513*ae771770SStanislav Sedov  *
514*ae771770SStanislav Sedov  */
515*ae771770SStanislav Sedov 
516*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_krb5_ccache_name(OM_uint32 * minor_status,const char * name,const char ** out_name)517*ae771770SStanislav Sedov gss_krb5_ccache_name(OM_uint32 *minor_status,
518*ae771770SStanislav Sedov 		     const char *name,
519*ae771770SStanislav Sedov 		     const char **out_name)
520*ae771770SStanislav Sedov {
521*ae771770SStanislav Sedov     struct _gss_mech_switch *m;
522*ae771770SStanislav Sedov     gss_buffer_desc buffer;
523*ae771770SStanislav Sedov     OM_uint32 junk;
524*ae771770SStanislav Sedov 
525*ae771770SStanislav Sedov     _gss_load_mech();
526*ae771770SStanislav Sedov 
527*ae771770SStanislav Sedov     if (out_name)
528*ae771770SStanislav Sedov 	*out_name = NULL;
529*ae771770SStanislav Sedov 
530*ae771770SStanislav Sedov     buffer.value = rk_UNCONST(name);
531*ae771770SStanislav Sedov     buffer.length = strlen(name);
532*ae771770SStanislav Sedov 
533*ae771770SStanislav Sedov     HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
534*ae771770SStanislav Sedov 	if (m->gm_mech.gm_set_sec_context_option == NULL)
535*ae771770SStanislav Sedov 	    continue;
536*ae771770SStanislav Sedov 	m->gm_mech.gm_set_sec_context_option(&junk, NULL,
537*ae771770SStanislav Sedov 	    GSS_KRB5_CCACHE_NAME_X, &buffer);
538*ae771770SStanislav Sedov     }
539*ae771770SStanislav Sedov 
540*ae771770SStanislav Sedov     return (GSS_S_COMPLETE);
541*ae771770SStanislav Sedov }
542*ae771770SStanislav Sedov 
543*ae771770SStanislav Sedov 
544*ae771770SStanislav Sedov /*
545*ae771770SStanislav Sedov  *
546*ae771770SStanislav Sedov  */
547*ae771770SStanislav Sedov 
548*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_extract_authtime_from_sec_context(OM_uint32 * minor_status,gss_ctx_id_t context_handle,time_t * authtime)549*ae771770SStanislav Sedov gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status,
550*ae771770SStanislav Sedov 					  gss_ctx_id_t context_handle,
551*ae771770SStanislav Sedov 					  time_t *authtime)
552*ae771770SStanislav Sedov {
553*ae771770SStanislav Sedov     gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
554*ae771770SStanislav Sedov     OM_uint32 maj_stat;
555*ae771770SStanislav Sedov 
556*ae771770SStanislav Sedov     if (context_handle == GSS_C_NO_CONTEXT) {
557*ae771770SStanislav Sedov 	*minor_status = EINVAL;
558*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
559*ae771770SStanislav Sedov     }
560*ae771770SStanislav Sedov 
561*ae771770SStanislav Sedov     maj_stat =
562*ae771770SStanislav Sedov 	gss_inquire_sec_context_by_oid (minor_status,
563*ae771770SStanislav Sedov 					context_handle,
564*ae771770SStanislav Sedov 					GSS_KRB5_GET_AUTHTIME_X,
565*ae771770SStanislav Sedov 					&data_set);
566*ae771770SStanislav Sedov     if (maj_stat)
567*ae771770SStanislav Sedov 	return maj_stat;
568*ae771770SStanislav Sedov 
569*ae771770SStanislav Sedov     if (data_set == GSS_C_NO_BUFFER_SET) {
570*ae771770SStanislav Sedov 	gss_release_buffer_set(minor_status, &data_set);
571*ae771770SStanislav Sedov 	*minor_status = EINVAL;
572*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
573*ae771770SStanislav Sedov     }
574*ae771770SStanislav Sedov 
575*ae771770SStanislav Sedov     if (data_set->count != 1) {
576*ae771770SStanislav Sedov 	gss_release_buffer_set(minor_status, &data_set);
577*ae771770SStanislav Sedov 	*minor_status = EINVAL;
578*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
579*ae771770SStanislav Sedov     }
580*ae771770SStanislav Sedov 
581*ae771770SStanislav Sedov     if (data_set->elements[0].length != 4) {
582*ae771770SStanislav Sedov 	gss_release_buffer_set(minor_status, &data_set);
583*ae771770SStanislav Sedov 	*minor_status = EINVAL;
584*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
585*ae771770SStanislav Sedov     }
586*ae771770SStanislav Sedov 
587*ae771770SStanislav Sedov     {
588*ae771770SStanislav Sedov 	unsigned char *buf = data_set->elements[0].value;
589*ae771770SStanislav Sedov 	*authtime = (buf[3] <<24) | (buf[2] << 16) |
590*ae771770SStanislav Sedov 	    (buf[1] << 8) | (buf[0] << 0);
591*ae771770SStanislav Sedov     }
592*ae771770SStanislav Sedov 
593*ae771770SStanislav Sedov     gss_release_buffer_set(minor_status, &data_set);
594*ae771770SStanislav Sedov 
595*ae771770SStanislav Sedov     *minor_status = 0;
596*ae771770SStanislav Sedov     return GSS_S_COMPLETE;
597*ae771770SStanislav Sedov }
598*ae771770SStanislav Sedov 
599*ae771770SStanislav Sedov /*
600*ae771770SStanislav Sedov  *
601*ae771770SStanislav Sedov  */
602*ae771770SStanislav Sedov 
603*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_extract_authz_data_from_sec_context(OM_uint32 * minor_status,gss_ctx_id_t context_handle,int ad_type,gss_buffer_t ad_data)604*ae771770SStanislav Sedov gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
605*ae771770SStanislav Sedov 					    gss_ctx_id_t context_handle,
606*ae771770SStanislav Sedov 					    int ad_type,
607*ae771770SStanislav Sedov 					    gss_buffer_t ad_data)
608*ae771770SStanislav Sedov {
609*ae771770SStanislav Sedov     gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
610*ae771770SStanislav Sedov     OM_uint32 maj_stat;
611*ae771770SStanislav Sedov     gss_OID_desc oid_flat;
612*ae771770SStanislav Sedov     heim_oid baseoid, oid;
613*ae771770SStanislav Sedov     size_t size;
614*ae771770SStanislav Sedov 
615*ae771770SStanislav Sedov     if (context_handle == GSS_C_NO_CONTEXT) {
616*ae771770SStanislav Sedov 	*minor_status = EINVAL;
617*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
618*ae771770SStanislav Sedov     }
619*ae771770SStanislav Sedov 
620*ae771770SStanislav Sedov     /* All this to append an integer to an oid... */
621*ae771770SStanislav Sedov 
622*ae771770SStanislav Sedov     if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements,
623*ae771770SStanislav Sedov 		    GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length,
624*ae771770SStanislav Sedov 		    &baseoid, NULL) != 0) {
625*ae771770SStanislav Sedov 	*minor_status = EINVAL;
626*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
627*ae771770SStanislav Sedov     }
628*ae771770SStanislav Sedov 
629*ae771770SStanislav Sedov     oid.length = baseoid.length + 1;
630*ae771770SStanislav Sedov     oid.components = calloc(oid.length, sizeof(*oid.components));
631*ae771770SStanislav Sedov     if (oid.components == NULL) {
632*ae771770SStanislav Sedov 	der_free_oid(&baseoid);
633*ae771770SStanislav Sedov 
634*ae771770SStanislav Sedov 	*minor_status = ENOMEM;
635*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
636*ae771770SStanislav Sedov     }
637*ae771770SStanislav Sedov 
638*ae771770SStanislav Sedov     memcpy(oid.components, baseoid.components,
639*ae771770SStanislav Sedov 	   baseoid.length * sizeof(*baseoid.components));
640*ae771770SStanislav Sedov 
641*ae771770SStanislav Sedov     der_free_oid(&baseoid);
642*ae771770SStanislav Sedov 
643*ae771770SStanislav Sedov     oid.components[oid.length - 1] = ad_type;
644*ae771770SStanislav Sedov 
645*ae771770SStanislav Sedov     oid_flat.length = der_length_oid(&oid);
646*ae771770SStanislav Sedov     oid_flat.elements = malloc(oid_flat.length);
647*ae771770SStanislav Sedov     if (oid_flat.elements == NULL) {
648*ae771770SStanislav Sedov 	free(oid.components);
649*ae771770SStanislav Sedov 	*minor_status = ENOMEM;
650*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
651*ae771770SStanislav Sedov     }
652*ae771770SStanislav Sedov 
653*ae771770SStanislav Sedov     if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1,
654*ae771770SStanislav Sedov 		    oid_flat.length, &oid, &size) != 0) {
655*ae771770SStanislav Sedov 	free(oid.components);
656*ae771770SStanislav Sedov 	free(oid_flat.elements);
657*ae771770SStanislav Sedov 	*minor_status = EINVAL;
658*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
659*ae771770SStanislav Sedov     }
660*ae771770SStanislav Sedov     if (oid_flat.length != size)
661*ae771770SStanislav Sedov 	abort();
662*ae771770SStanislav Sedov 
663*ae771770SStanislav Sedov     free(oid.components);
664*ae771770SStanislav Sedov 
665*ae771770SStanislav Sedov     /* FINALLY, we have the OID */
666*ae771770SStanislav Sedov 
667*ae771770SStanislav Sedov     maj_stat = gss_inquire_sec_context_by_oid (minor_status,
668*ae771770SStanislav Sedov 					       context_handle,
669*ae771770SStanislav Sedov 					       &oid_flat,
670*ae771770SStanislav Sedov 					       &data_set);
671*ae771770SStanislav Sedov 
672*ae771770SStanislav Sedov     free(oid_flat.elements);
673*ae771770SStanislav Sedov 
674*ae771770SStanislav Sedov     if (maj_stat)
675*ae771770SStanislav Sedov 	return maj_stat;
676*ae771770SStanislav Sedov 
677*ae771770SStanislav Sedov     if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
678*ae771770SStanislav Sedov 	gss_release_buffer_set(minor_status, &data_set);
679*ae771770SStanislav Sedov 	*minor_status = EINVAL;
680*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
681*ae771770SStanislav Sedov     }
682*ae771770SStanislav Sedov 
683*ae771770SStanislav Sedov     ad_data->value = malloc(data_set->elements[0].length);
684*ae771770SStanislav Sedov     if (ad_data->value == NULL) {
685*ae771770SStanislav Sedov 	gss_release_buffer_set(minor_status, &data_set);
686*ae771770SStanislav Sedov 	*minor_status = ENOMEM;
687*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
688*ae771770SStanislav Sedov     }
689*ae771770SStanislav Sedov 
690*ae771770SStanislav Sedov     ad_data->length = data_set->elements[0].length;
691*ae771770SStanislav Sedov     memcpy(ad_data->value, data_set->elements[0].value, ad_data->length);
692*ae771770SStanislav Sedov     gss_release_buffer_set(minor_status, &data_set);
693*ae771770SStanislav Sedov 
694*ae771770SStanislav Sedov     *minor_status = 0;
695*ae771770SStanislav Sedov     return GSS_S_COMPLETE;
696*ae771770SStanislav Sedov }
697*ae771770SStanislav Sedov 
698*ae771770SStanislav Sedov /*
699*ae771770SStanislav Sedov  *
700*ae771770SStanislav Sedov  */
701*ae771770SStanislav Sedov 
702*ae771770SStanislav Sedov static OM_uint32
gsskrb5_extract_key(OM_uint32 * minor_status,gss_ctx_id_t context_handle,const gss_OID oid,krb5_keyblock ** keyblock)703*ae771770SStanislav Sedov gsskrb5_extract_key(OM_uint32 *minor_status,
704*ae771770SStanislav Sedov 		    gss_ctx_id_t context_handle,
705*ae771770SStanislav Sedov 		    const gss_OID oid,
706*ae771770SStanislav Sedov 		    krb5_keyblock **keyblock)
707*ae771770SStanislav Sedov {
708*ae771770SStanislav Sedov     krb5_error_code ret;
709*ae771770SStanislav Sedov     gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
710*ae771770SStanislav Sedov     OM_uint32 major_status;
711*ae771770SStanislav Sedov     krb5_context context = NULL;
712*ae771770SStanislav Sedov     krb5_storage *sp = NULL;
713*ae771770SStanislav Sedov 
714*ae771770SStanislav Sedov     if (context_handle == GSS_C_NO_CONTEXT) {
715*ae771770SStanislav Sedov 	*minor_status = EINVAL;
716*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
717*ae771770SStanislav Sedov     }
718*ae771770SStanislav Sedov 
719*ae771770SStanislav Sedov     ret = krb5_init_context(&context);
720*ae771770SStanislav Sedov     if(ret) {
721*ae771770SStanislav Sedov 	*minor_status = ret;
722*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
723*ae771770SStanislav Sedov     }
724*ae771770SStanislav Sedov 
725*ae771770SStanislav Sedov     major_status =
726*ae771770SStanislav Sedov 	gss_inquire_sec_context_by_oid (minor_status,
727*ae771770SStanislav Sedov 					context_handle,
728*ae771770SStanislav Sedov 					oid,
729*ae771770SStanislav Sedov 					&data_set);
730*ae771770SStanislav Sedov     if (major_status)
731*ae771770SStanislav Sedov 	return major_status;
732*ae771770SStanislav Sedov 
733*ae771770SStanislav Sedov     if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) {
734*ae771770SStanislav Sedov 	gss_release_buffer_set(minor_status, &data_set);
735*ae771770SStanislav Sedov 	*minor_status = EINVAL;
736*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
737*ae771770SStanislav Sedov     }
738*ae771770SStanislav Sedov 
739*ae771770SStanislav Sedov     sp = krb5_storage_from_mem(data_set->elements[0].value,
740*ae771770SStanislav Sedov 			       data_set->elements[0].length);
741*ae771770SStanislav Sedov     if (sp == NULL) {
742*ae771770SStanislav Sedov 	ret = ENOMEM;
743*ae771770SStanislav Sedov 	goto out;
744*ae771770SStanislav Sedov     }
745*ae771770SStanislav Sedov 
746*ae771770SStanislav Sedov     *keyblock = calloc(1, sizeof(**keyblock));
747*ae771770SStanislav Sedov     if (keyblock == NULL) {
748*ae771770SStanislav Sedov 	ret = ENOMEM;
749*ae771770SStanislav Sedov 	goto out;
750*ae771770SStanislav Sedov     }
751*ae771770SStanislav Sedov 
752*ae771770SStanislav Sedov     ret = krb5_ret_keyblock(sp, *keyblock);
753*ae771770SStanislav Sedov 
754*ae771770SStanislav Sedov out:
755*ae771770SStanislav Sedov     gss_release_buffer_set(minor_status, &data_set);
756*ae771770SStanislav Sedov     if (sp)
757*ae771770SStanislav Sedov 	krb5_storage_free(sp);
758*ae771770SStanislav Sedov     if (ret && keyblock) {
759*ae771770SStanislav Sedov 	krb5_free_keyblock(context, *keyblock);
760*ae771770SStanislav Sedov 	*keyblock = NULL;
761*ae771770SStanislav Sedov     }
762*ae771770SStanislav Sedov     if (context)
763*ae771770SStanislav Sedov 	krb5_free_context(context);
764*ae771770SStanislav Sedov 
765*ae771770SStanislav Sedov     *minor_status = ret;
766*ae771770SStanislav Sedov     if (ret)
767*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
768*ae771770SStanislav Sedov 
769*ae771770SStanislav Sedov     return GSS_S_COMPLETE;
770*ae771770SStanislav Sedov }
771*ae771770SStanislav Sedov 
772*ae771770SStanislav Sedov /*
773*ae771770SStanislav Sedov  *
774*ae771770SStanislav Sedov  */
775*ae771770SStanislav Sedov 
776*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_extract_service_keyblock(OM_uint32 * minor_status,gss_ctx_id_t context_handle,krb5_keyblock ** keyblock)777*ae771770SStanislav Sedov gsskrb5_extract_service_keyblock(OM_uint32 *minor_status,
778*ae771770SStanislav Sedov 				 gss_ctx_id_t context_handle,
779*ae771770SStanislav Sedov 				 krb5_keyblock **keyblock)
780*ae771770SStanislav Sedov {
781*ae771770SStanislav Sedov     return gsskrb5_extract_key(minor_status,
782*ae771770SStanislav Sedov 			       context_handle,
783*ae771770SStanislav Sedov 			       GSS_KRB5_GET_SERVICE_KEYBLOCK_X,
784*ae771770SStanislav Sedov 			       keyblock);
785*ae771770SStanislav Sedov }
786*ae771770SStanislav Sedov 
787*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_get_initiator_subkey(OM_uint32 * minor_status,gss_ctx_id_t context_handle,krb5_keyblock ** keyblock)788*ae771770SStanislav Sedov gsskrb5_get_initiator_subkey(OM_uint32 *minor_status,
789*ae771770SStanislav Sedov 			     gss_ctx_id_t context_handle,
790*ae771770SStanislav Sedov 			     krb5_keyblock **keyblock)
791*ae771770SStanislav Sedov {
792*ae771770SStanislav Sedov     return gsskrb5_extract_key(minor_status,
793*ae771770SStanislav Sedov 			       context_handle,
794*ae771770SStanislav Sedov 			       GSS_KRB5_GET_INITIATOR_SUBKEY_X,
795*ae771770SStanislav Sedov 			       keyblock);
796*ae771770SStanislav Sedov }
797*ae771770SStanislav Sedov 
798*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_get_subkey(OM_uint32 * minor_status,gss_ctx_id_t context_handle,krb5_keyblock ** keyblock)799*ae771770SStanislav Sedov gsskrb5_get_subkey(OM_uint32 *minor_status,
800*ae771770SStanislav Sedov 		   gss_ctx_id_t context_handle,
801*ae771770SStanislav Sedov 		   krb5_keyblock **keyblock)
802*ae771770SStanislav Sedov {
803*ae771770SStanislav Sedov     return gsskrb5_extract_key(minor_status,
804*ae771770SStanislav Sedov 			       context_handle,
805*ae771770SStanislav Sedov 			       GSS_KRB5_GET_SUBKEY_X,
806*ae771770SStanislav Sedov 			       keyblock);
807*ae771770SStanislav Sedov }
808*ae771770SStanislav Sedov 
809*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_set_default_realm(const char * realm)810*ae771770SStanislav Sedov gsskrb5_set_default_realm(const char *realm)
811*ae771770SStanislav Sedov {
812*ae771770SStanislav Sedov         struct _gss_mech_switch	*m;
813*ae771770SStanislav Sedov 	gss_buffer_desc buffer;
814*ae771770SStanislav Sedov 	OM_uint32 junk;
815*ae771770SStanislav Sedov 
816*ae771770SStanislav Sedov 	_gss_load_mech();
817*ae771770SStanislav Sedov 
818*ae771770SStanislav Sedov 	buffer.value = rk_UNCONST(realm);
819*ae771770SStanislav Sedov 	buffer.length = strlen(realm);
820*ae771770SStanislav Sedov 
821*ae771770SStanislav Sedov 	HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
822*ae771770SStanislav Sedov 		if (m->gm_mech.gm_set_sec_context_option == NULL)
823*ae771770SStanislav Sedov 			continue;
824*ae771770SStanislav Sedov 		m->gm_mech.gm_set_sec_context_option(&junk, NULL,
825*ae771770SStanislav Sedov 		    GSS_KRB5_SET_DEFAULT_REALM_X, &buffer);
826*ae771770SStanislav Sedov 	}
827*ae771770SStanislav Sedov 
828*ae771770SStanislav Sedov 	return (GSS_S_COMPLETE);
829*ae771770SStanislav Sedov }
830*ae771770SStanislav Sedov 
831*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_krb5_get_tkt_flags(OM_uint32 * minor_status,gss_ctx_id_t context_handle,OM_uint32 * tkt_flags)832*ae771770SStanislav Sedov gss_krb5_get_tkt_flags(OM_uint32 *minor_status,
833*ae771770SStanislav Sedov 		       gss_ctx_id_t context_handle,
834*ae771770SStanislav Sedov 		       OM_uint32 *tkt_flags)
835*ae771770SStanislav Sedov {
836*ae771770SStanislav Sedov 
837*ae771770SStanislav Sedov     OM_uint32 major_status;
838*ae771770SStanislav Sedov     gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
839*ae771770SStanislav Sedov 
840*ae771770SStanislav Sedov     if (context_handle == GSS_C_NO_CONTEXT) {
841*ae771770SStanislav Sedov 	*minor_status = EINVAL;
842*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
843*ae771770SStanislav Sedov     }
844*ae771770SStanislav Sedov 
845*ae771770SStanislav Sedov     major_status =
846*ae771770SStanislav Sedov 	gss_inquire_sec_context_by_oid (minor_status,
847*ae771770SStanislav Sedov 					context_handle,
848*ae771770SStanislav Sedov 					GSS_KRB5_GET_TKT_FLAGS_X,
849*ae771770SStanislav Sedov 					&data_set);
850*ae771770SStanislav Sedov     if (major_status)
851*ae771770SStanislav Sedov 	return major_status;
852*ae771770SStanislav Sedov 
853*ae771770SStanislav Sedov     if (data_set == GSS_C_NO_BUFFER_SET ||
854*ae771770SStanislav Sedov 	data_set->count != 1 ||
855*ae771770SStanislav Sedov 	data_set->elements[0].length < 4) {
856*ae771770SStanislav Sedov 	gss_release_buffer_set(minor_status, &data_set);
857*ae771770SStanislav Sedov 	*minor_status = EINVAL;
858*ae771770SStanislav Sedov 	return GSS_S_FAILURE;
859*ae771770SStanislav Sedov     }
860*ae771770SStanislav Sedov 
861*ae771770SStanislav Sedov     {
862*ae771770SStanislav Sedov 	const u_char *p = data_set->elements[0].value;
863*ae771770SStanislav Sedov 	*tkt_flags = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
864*ae771770SStanislav Sedov     }
865*ae771770SStanislav Sedov 
866*ae771770SStanislav Sedov     gss_release_buffer_set(minor_status, &data_set);
867*ae771770SStanislav Sedov     return GSS_S_COMPLETE;
868*ae771770SStanislav Sedov }
869*ae771770SStanislav Sedov 
870*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_set_time_offset(int offset)871*ae771770SStanislav Sedov gsskrb5_set_time_offset(int offset)
872*ae771770SStanislav Sedov {
873*ae771770SStanislav Sedov         struct _gss_mech_switch	*m;
874*ae771770SStanislav Sedov 	gss_buffer_desc buffer;
875*ae771770SStanislav Sedov 	OM_uint32 junk;
876*ae771770SStanislav Sedov 	int32_t o = offset;
877*ae771770SStanislav Sedov 
878*ae771770SStanislav Sedov 	_gss_load_mech();
879*ae771770SStanislav Sedov 
880*ae771770SStanislav Sedov 	buffer.value = &o;
881*ae771770SStanislav Sedov 	buffer.length = sizeof(o);
882*ae771770SStanislav Sedov 
883*ae771770SStanislav Sedov 	HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
884*ae771770SStanislav Sedov 		if (m->gm_mech.gm_set_sec_context_option == NULL)
885*ae771770SStanislav Sedov 			continue;
886*ae771770SStanislav Sedov 		m->gm_mech.gm_set_sec_context_option(&junk, NULL,
887*ae771770SStanislav Sedov 		    GSS_KRB5_SET_TIME_OFFSET_X, &buffer);
888*ae771770SStanislav Sedov 	}
889*ae771770SStanislav Sedov 
890*ae771770SStanislav Sedov 	return (GSS_S_COMPLETE);
891*ae771770SStanislav Sedov }
892*ae771770SStanislav Sedov 
893*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_get_time_offset(int * offset)894*ae771770SStanislav Sedov gsskrb5_get_time_offset(int *offset)
895*ae771770SStanislav Sedov {
896*ae771770SStanislav Sedov         struct _gss_mech_switch	*m;
897*ae771770SStanislav Sedov 	gss_buffer_desc buffer;
898*ae771770SStanislav Sedov 	OM_uint32 maj_stat, junk;
899*ae771770SStanislav Sedov 	int32_t o;
900*ae771770SStanislav Sedov 
901*ae771770SStanislav Sedov 	_gss_load_mech();
902*ae771770SStanislav Sedov 
903*ae771770SStanislav Sedov 	buffer.value = &o;
904*ae771770SStanislav Sedov 	buffer.length = sizeof(o);
905*ae771770SStanislav Sedov 
906*ae771770SStanislav Sedov 	HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
907*ae771770SStanislav Sedov 		if (m->gm_mech.gm_set_sec_context_option == NULL)
908*ae771770SStanislav Sedov 			continue;
909*ae771770SStanislav Sedov 		maj_stat = m->gm_mech.gm_set_sec_context_option(&junk, NULL,
910*ae771770SStanislav Sedov 		    GSS_KRB5_GET_TIME_OFFSET_X, &buffer);
911*ae771770SStanislav Sedov 
912*ae771770SStanislav Sedov 		if (maj_stat == GSS_S_COMPLETE) {
913*ae771770SStanislav Sedov 			*offset = o;
914*ae771770SStanislav Sedov 			return maj_stat;
915*ae771770SStanislav Sedov 		}
916*ae771770SStanislav Sedov 	}
917*ae771770SStanislav Sedov 
918*ae771770SStanislav Sedov 	return (GSS_S_UNAVAILABLE);
919*ae771770SStanislav Sedov }
920*ae771770SStanislav Sedov 
921*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gsskrb5_plugin_register(struct gsskrb5_krb5_plugin * c)922*ae771770SStanislav Sedov gsskrb5_plugin_register(struct gsskrb5_krb5_plugin *c)
923*ae771770SStanislav Sedov {
924*ae771770SStanislav Sedov     struct _gss_mech_switch *m;
925*ae771770SStanislav Sedov     gss_buffer_desc buffer;
926*ae771770SStanislav Sedov     OM_uint32 junk;
927*ae771770SStanislav Sedov 
928*ae771770SStanislav Sedov     _gss_load_mech();
929*ae771770SStanislav Sedov 
930*ae771770SStanislav Sedov     buffer.value = c;
931*ae771770SStanislav Sedov     buffer.length = sizeof(*c);
932*ae771770SStanislav Sedov 
933*ae771770SStanislav Sedov     HEIM_SLIST_FOREACH(m, &_gss_mechs, gm_link) {
934*ae771770SStanislav Sedov 	if (m->gm_mech.gm_set_sec_context_option == NULL)
935*ae771770SStanislav Sedov 	    continue;
936*ae771770SStanislav Sedov 	m->gm_mech.gm_set_sec_context_option(&junk, NULL,
937*ae771770SStanislav Sedov 	    GSS_KRB5_PLUGIN_REGISTER_X, &buffer);
938*ae771770SStanislav Sedov     }
939*ae771770SStanislav Sedov 
940*ae771770SStanislav Sedov     return (GSS_S_COMPLETE);
941*ae771770SStanislav Sedov }
942