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