set_cred_option.c revision 233294
1193323Sed/*
2193323Sed * Copyright (c) 2004, PADL Software Pty Ltd.
3193323Sed * All rights reserved.
4193323Sed *
5193323Sed * Redistribution and use in source and binary forms, with or without
6193323Sed * modification, are permitted provided that the following conditions
7193323Sed * are met:
8193323Sed *
9193323Sed * 1. Redistributions of source code must retain the above copyright
10193323Sed *    notice, this list of conditions and the following disclaimer.
11193323Sed *
12193323Sed * 2. Redistributions in binary form must reproduce the above copyright
13193323Sed *    notice, this list of conditions and the following disclaimer in the
14193323Sed *    documentation and/or other materials provided with the distribution.
15193323Sed *
16193323Sed * 3. Neither the name of PADL Software nor the names of its contributors
17193323Sed *    may be used to endorse or promote products derived from this software
18193323Sed *    without specific prior written permission.
19193323Sed *
20193323Sed * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23249423Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24249423Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25249423Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26249423Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27249423Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28249423Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29249423Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30193323Sed * SUCH DAMAGE.
31193323Sed */
32198090Srdivacky
33193323Sed#include "gsskrb5_locl.h"
34198090Srdivacky
35249423Sdimstatic OM_uint32
36249423Sdimimport_cred(OM_uint32 *minor_status,
37249423Sdim	    krb5_context context,
38263508Sdim            gss_cred_id_t *cred_handle,
39263508Sdim            const gss_buffer_t value)
40193323Sed{
41193323Sed    OM_uint32 major_stat;
42193323Sed    krb5_error_code ret;
43193323Sed    krb5_principal keytab_principal = NULL;
44193323Sed    krb5_keytab keytab = NULL;
45193323Sed    krb5_storage *sp = NULL;
46193323Sed    krb5_ccache id = NULL;
47218893Sdim    char *str;
48263508Sdim
49193323Sed    if (cred_handle == NULL || *cred_handle != GSS_C_NO_CREDENTIAL) {
50193323Sed	*minor_status = 0;
51193323Sed	return GSS_S_FAILURE;
52193323Sed    }
53193323Sed
54193323Sed    sp = krb5_storage_from_mem(value->value, value->length);
55193323Sed    if (sp == NULL) {
56193323Sed	*minor_status = 0;
57193323Sed	return GSS_S_FAILURE;
58193323Sed    }
59263508Sdim
60263508Sdim    /* credential cache name */
61263508Sdim    ret = krb5_ret_string(sp, &str);
62263508Sdim    if (ret) {
63263508Sdim	*minor_status = ret;
64263508Sdim	major_stat =  GSS_S_FAILURE;
65263508Sdim	goto out;
66263508Sdim    }
67193323Sed    if (str[0]) {
68193323Sed	ret = krb5_cc_resolve(context, str, &id);
69198892Srdivacky	if (ret) {
70193323Sed	    *minor_status = ret;
71193323Sed	    major_stat =  GSS_S_FAILURE;
72193323Sed	    goto out;
73193323Sed	}
74193323Sed    }
75193323Sed    free(str);
76263508Sdim    str = NULL;
77193323Sed
78193323Sed    /* keytab principal name */
79234353Sdim    ret = krb5_ret_string(sp, &str);
80234353Sdim    if (ret == 0 && str[0])
81234353Sdim	ret = krb5_parse_name(context, str, &keytab_principal);
82234353Sdim    if (ret) {
83234353Sdim	*minor_status = ret;
84234353Sdim	major_stat = GSS_S_FAILURE;
85234353Sdim	goto out;
86234353Sdim    }
87234353Sdim    free(str);
88234353Sdim    str = NULL;
89234353Sdim
90234353Sdim    /* keytab principal */
91234353Sdim    ret = krb5_ret_string(sp, &str);
92234353Sdim    if (ret) {
93234353Sdim	*minor_status = ret;
94234353Sdim	major_stat =  GSS_S_FAILURE;
95234353Sdim	goto out;
96234353Sdim    }
97193323Sed    if (str[0]) {
98193323Sed	ret = krb5_kt_resolve(context, str, &keytab);
99193323Sed	if (ret) {
100193323Sed	    *minor_status = ret;
101193323Sed	    major_stat =  GSS_S_FAILURE;
102193323Sed	    goto out;
103193323Sed	}
104193323Sed    }
105193323Sed    free(str);
106193323Sed    str = NULL;
107193323Sed
108193323Sed    major_stat = _gsskrb5_krb5_import_cred(minor_status, id, keytab_principal,
109193323Sed					   keytab, cred_handle);
110193323Sedout:
111193323Sed    if (id)
112193323Sed	krb5_cc_close(context, id);
113193323Sed    if (keytab_principal)
114193323Sed	krb5_free_principal(context, keytab_principal);
115193323Sed    if (keytab)
116234353Sdim	krb5_kt_close(context, keytab);
117234353Sdim    if (str)
118193323Sed	free(str);
119234353Sdim    if (sp)
120234353Sdim	krb5_storage_free(sp);
121193323Sed
122193323Sed    return major_stat;
123193323Sed}
124193323Sed
125193323Sed
126234353Sdimstatic OM_uint32
127193323Sedallowed_enctypes(OM_uint32 *minor_status,
128193323Sed		 krb5_context context,
129193323Sed		 gss_cred_id_t *cred_handle,
130193323Sed		 const gss_buffer_t value)
131193323Sed{
132193323Sed    OM_uint32 major_stat;
133193323Sed    krb5_error_code ret;
134193323Sed    size_t len, i;
135193323Sed    krb5_enctype *enctypes = NULL;
136193323Sed    krb5_storage *sp = NULL;
137193323Sed    gsskrb5_cred cred;
138193323Sed
139193323Sed    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
140193323Sed	*minor_status = 0;
141193323Sed	return GSS_S_FAILURE;
142193323Sed    }
143193323Sed
144193323Sed    cred = (gsskrb5_cred)*cred_handle;
145193323Sed
146193323Sed    if ((value->length % 4) != 0) {
147193323Sed	*minor_status = 0;
148193323Sed	major_stat = GSS_S_FAILURE;
149193323Sed	goto out;
150200581Srdivacky    }
151200581Srdivacky
152193323Sed    len = value->length / 4;
153193323Sed    enctypes = malloc((len + 1) * 4);
154193323Sed    if (enctypes == NULL) {
155193323Sed	*minor_status = ENOMEM;
156193323Sed	major_stat = GSS_S_FAILURE;
157193323Sed	goto out;
158193323Sed    }
159263508Sdim
160193323Sed    sp = krb5_storage_from_mem(value->value, value->length);
161207618Srdivacky    if (sp == NULL) {
162207618Srdivacky	*minor_status = ENOMEM;
163207618Srdivacky	major_stat = GSS_S_FAILURE;
164207618Srdivacky	goto out;
165207618Srdivacky    }
166207618Srdivacky
167207618Srdivacky    for (i = 0; i < len; i++) {
168207618Srdivacky	uint32_t e;
169193323Sed
170263508Sdim	ret = krb5_ret_uint32(sp, &e);
171263508Sdim	if (ret) {
172224145Sdim	    *minor_status = ret;
173224145Sdim	    major_stat =  GSS_S_FAILURE;
174193323Sed	    goto out;
175193323Sed	}
176193323Sed	enctypes[i] = e;
177193323Sed    }
178193323Sed    enctypes[i] = 0;
179193323Sed
180193323Sed    if (cred->enctypes)
181193323Sed	free(cred->enctypes);
182193323Sed    cred->enctypes = enctypes;
183193323Sed
184193323Sed    krb5_storage_free(sp);
185193323Sed
186193323Sed    return GSS_S_COMPLETE;
187193323Sed
188193323Sedout:
189193323Sed    if (sp)
190193323Sed	krb5_storage_free(sp);
191234353Sdim    if (enctypes)
192193323Sed	free(enctypes);
193234353Sdim
194193323Sed    return major_stat;
195193323Sed}
196193323Sed
197193323Sedstatic OM_uint32
198193323Sedno_ci_flags(OM_uint32 *minor_status,
199193323Sed	    krb5_context context,
200193323Sed	    gss_cred_id_t *cred_handle,
201193323Sed	    const gss_buffer_t value)
202193323Sed{
203223017Sdim    gsskrb5_cred cred;
204223017Sdim
205193323Sed    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
206193323Sed	*minor_status = 0;
207193323Sed	return GSS_S_FAILURE;
208193323Sed    }
209193323Sed
210193323Sed    cred = (gsskrb5_cred)*cred_handle;
211243830Sdim    cred->cred_flags |= GSS_CF_NO_CI_FLAGS;
212193323Sed
213193323Sed    *minor_status = 0;
214193323Sed    return GSS_S_COMPLETE;
215193323Sed
216234353Sdim}
217193323Sed
218234353Sdim
219193323SedOM_uint32 GSSAPI_CALLCONV
220193323Sed_gsskrb5_set_cred_option
221251662Sdim           (OM_uint32 *minor_status,
222193323Sed            gss_cred_id_t *cred_handle,
223193323Sed            const gss_OID desired_object,
224193323Sed            const gss_buffer_t value)
225193323Sed{
226193323Sed    krb5_context context;
227193323Sed
228193323Sed    GSSAPI_KRB5_INIT (&context);
229218893Sdim
230193323Sed    if (value == GSS_C_NO_BUFFER) {
231193323Sed	*minor_status = EINVAL;
232193323Sed	return GSS_S_FAILURE;
233193323Sed    }
234239462Sdim
235193323Sed    if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_CRED_X))
236193323Sed	return import_cred(minor_status, context, cred_handle, value);
237193323Sed
238193323Sed    if (gss_oid_equal(desired_object, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X))
239193323Sed	return allowed_enctypes(minor_status, context, cred_handle, value);
240193323Sed
241193323Sed    if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_CI_FLAGS_X)) {
242193323Sed	return no_ci_flags(minor_status, context, cred_handle, value);
243193323Sed    }
244193323Sed
245193323Sed
246193323Sed    *minor_status = EINVAL;
247239462Sdim    return GSS_S_FAILURE;
248239462Sdim}
249239462Sdim