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