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