1178825Sdfr/*
2178825Sdfr * Copyright (c) 2004, PADL Software Pty Ltd.
3178825Sdfr * All rights reserved.
4178825Sdfr *
5178825Sdfr * Redistribution and use in source and binary forms, with or without
6178825Sdfr * modification, are permitted provided that the following conditions
7178825Sdfr * are met:
8178825Sdfr *
9178825Sdfr * 1. Redistributions of source code must retain the above copyright
10178825Sdfr *    notice, this list of conditions and the following disclaimer.
11178825Sdfr *
12178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright
13178825Sdfr *    notice, this list of conditions and the following disclaimer in the
14178825Sdfr *    documentation and/or other materials provided with the distribution.
15178825Sdfr *
16178825Sdfr * 3. Neither the name of PADL Software nor the names of its contributors
17178825Sdfr *    may be used to endorse or promote products derived from this software
18178825Sdfr *    without specific prior written permission.
19178825Sdfr *
20178825Sdfr * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23178825Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30178825Sdfr * SUCH DAMAGE.
31178825Sdfr */
32178825Sdfr
33233294Sstas#include "gsskrb5_locl.h"
34178825Sdfr
35178825Sdfrstatic OM_uint32
36178825Sdfrimport_cred(OM_uint32 *minor_status,
37178825Sdfr	    krb5_context context,
38178825Sdfr            gss_cred_id_t *cred_handle,
39178825Sdfr            const gss_buffer_t value)
40178825Sdfr{
41178825Sdfr    OM_uint32 major_stat;
42178825Sdfr    krb5_error_code ret;
43178825Sdfr    krb5_principal keytab_principal = NULL;
44178825Sdfr    krb5_keytab keytab = NULL;
45178825Sdfr    krb5_storage *sp = NULL;
46178825Sdfr    krb5_ccache id = NULL;
47178825Sdfr    char *str;
48178825Sdfr
49178825Sdfr    if (cred_handle == NULL || *cred_handle != GSS_C_NO_CREDENTIAL) {
50178825Sdfr	*minor_status = 0;
51178825Sdfr	return GSS_S_FAILURE;
52178825Sdfr    }
53178825Sdfr
54178825Sdfr    sp = krb5_storage_from_mem(value->value, value->length);
55178825Sdfr    if (sp == NULL) {
56178825Sdfr	*minor_status = 0;
57178825Sdfr	return GSS_S_FAILURE;
58178825Sdfr    }
59178825Sdfr
60178825Sdfr    /* credential cache name */
61178825Sdfr    ret = krb5_ret_string(sp, &str);
62178825Sdfr    if (ret) {
63178825Sdfr	*minor_status = ret;
64178825Sdfr	major_stat =  GSS_S_FAILURE;
65178825Sdfr	goto out;
66178825Sdfr    }
67178825Sdfr    if (str[0]) {
68178825Sdfr	ret = krb5_cc_resolve(context, str, &id);
69178825Sdfr	if (ret) {
70178825Sdfr	    *minor_status = ret;
71178825Sdfr	    major_stat =  GSS_S_FAILURE;
72178825Sdfr	    goto out;
73178825Sdfr	}
74178825Sdfr    }
75178825Sdfr    free(str);
76178825Sdfr    str = NULL;
77178825Sdfr
78178825Sdfr    /* keytab principal name */
79178825Sdfr    ret = krb5_ret_string(sp, &str);
80178825Sdfr    if (ret == 0 && str[0])
81178825Sdfr	ret = krb5_parse_name(context, str, &keytab_principal);
82178825Sdfr    if (ret) {
83178825Sdfr	*minor_status = ret;
84178825Sdfr	major_stat = GSS_S_FAILURE;
85178825Sdfr	goto out;
86178825Sdfr    }
87178825Sdfr    free(str);
88178825Sdfr    str = NULL;
89178825Sdfr
90178825Sdfr    /* keytab principal */
91178825Sdfr    ret = krb5_ret_string(sp, &str);
92178825Sdfr    if (ret) {
93178825Sdfr	*minor_status = ret;
94178825Sdfr	major_stat =  GSS_S_FAILURE;
95178825Sdfr	goto out;
96178825Sdfr    }
97178825Sdfr    if (str[0]) {
98178825Sdfr	ret = krb5_kt_resolve(context, str, &keytab);
99178825Sdfr	if (ret) {
100178825Sdfr	    *minor_status = ret;
101178825Sdfr	    major_stat =  GSS_S_FAILURE;
102178825Sdfr	    goto out;
103178825Sdfr	}
104178825Sdfr    }
105178825Sdfr    free(str);
106178825Sdfr    str = NULL;
107178825Sdfr
108233294Sstas    major_stat = _gsskrb5_krb5_import_cred(minor_status, id, keytab_principal,
109233294Sstas					   keytab, cred_handle);
110178825Sdfrout:
111178825Sdfr    if (id)
112178825Sdfr	krb5_cc_close(context, id);
113178825Sdfr    if (keytab_principal)
114178825Sdfr	krb5_free_principal(context, keytab_principal);
115178825Sdfr    if (keytab)
116178825Sdfr	krb5_kt_close(context, keytab);
117178825Sdfr    if (str)
118178825Sdfr	free(str);
119178825Sdfr    if (sp)
120178825Sdfr	krb5_storage_free(sp);
121178825Sdfr
122178825Sdfr    return major_stat;
123178825Sdfr}
124178825Sdfr
125178825Sdfr
126178825Sdfrstatic OM_uint32
127178825Sdfrallowed_enctypes(OM_uint32 *minor_status,
128178825Sdfr		 krb5_context context,
129178825Sdfr		 gss_cred_id_t *cred_handle,
130178825Sdfr		 const gss_buffer_t value)
131178825Sdfr{
132178825Sdfr    OM_uint32 major_stat;
133178825Sdfr    krb5_error_code ret;
134178825Sdfr    size_t len, i;
135178825Sdfr    krb5_enctype *enctypes = NULL;
136178825Sdfr    krb5_storage *sp = NULL;
137178825Sdfr    gsskrb5_cred cred;
138178825Sdfr
139178825Sdfr    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
140178825Sdfr	*minor_status = 0;
141178825Sdfr	return GSS_S_FAILURE;
142178825Sdfr    }
143178825Sdfr
144178825Sdfr    cred = (gsskrb5_cred)*cred_handle;
145178825Sdfr
146178825Sdfr    if ((value->length % 4) != 0) {
147178825Sdfr	*minor_status = 0;
148178825Sdfr	major_stat = GSS_S_FAILURE;
149178825Sdfr	goto out;
150178825Sdfr    }
151178825Sdfr
152178825Sdfr    len = value->length / 4;
153178825Sdfr    enctypes = malloc((len + 1) * 4);
154178825Sdfr    if (enctypes == NULL) {
155178825Sdfr	*minor_status = ENOMEM;
156178825Sdfr	major_stat = GSS_S_FAILURE;
157178825Sdfr	goto out;
158178825Sdfr    }
159178825Sdfr
160178825Sdfr    sp = krb5_storage_from_mem(value->value, value->length);
161178825Sdfr    if (sp == NULL) {
162178825Sdfr	*minor_status = ENOMEM;
163178825Sdfr	major_stat = GSS_S_FAILURE;
164178825Sdfr	goto out;
165178825Sdfr    }
166178825Sdfr
167178825Sdfr    for (i = 0; i < len; i++) {
168178825Sdfr	uint32_t e;
169178825Sdfr
170178825Sdfr	ret = krb5_ret_uint32(sp, &e);
171178825Sdfr	if (ret) {
172178825Sdfr	    *minor_status = ret;
173178825Sdfr	    major_stat =  GSS_S_FAILURE;
174178825Sdfr	    goto out;
175178825Sdfr	}
176178825Sdfr	enctypes[i] = e;
177178825Sdfr    }
178178825Sdfr    enctypes[i] = 0;
179178825Sdfr
180178825Sdfr    if (cred->enctypes)
181178825Sdfr	free(cred->enctypes);
182178825Sdfr    cred->enctypes = enctypes;
183178825Sdfr
184178825Sdfr    krb5_storage_free(sp);
185178825Sdfr
186178825Sdfr    return GSS_S_COMPLETE;
187178825Sdfr
188178825Sdfrout:
189178825Sdfr    if (sp)
190178825Sdfr	krb5_storage_free(sp);
191178825Sdfr    if (enctypes)
192178825Sdfr	free(enctypes);
193178825Sdfr
194178825Sdfr    return major_stat;
195178825Sdfr}
196178825Sdfr
197233294Sstasstatic OM_uint32
198233294Sstasno_ci_flags(OM_uint32 *minor_status,
199233294Sstas	    krb5_context context,
200233294Sstas	    gss_cred_id_t *cred_handle,
201233294Sstas	    const gss_buffer_t value)
202233294Sstas{
203233294Sstas    gsskrb5_cred cred;
204178825Sdfr
205233294Sstas    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
206233294Sstas	*minor_status = 0;
207233294Sstas	return GSS_S_FAILURE;
208233294Sstas    }
209233294Sstas
210233294Sstas    cred = (gsskrb5_cred)*cred_handle;
211233294Sstas    cred->cred_flags |= GSS_CF_NO_CI_FLAGS;
212233294Sstas
213233294Sstas    *minor_status = 0;
214233294Sstas    return GSS_S_COMPLETE;
215233294Sstas
216233294Sstas}
217233294Sstas
218233294Sstas
219233294SstasOM_uint32 GSSAPI_CALLCONV
220178825Sdfr_gsskrb5_set_cred_option
221178825Sdfr           (OM_uint32 *minor_status,
222178825Sdfr            gss_cred_id_t *cred_handle,
223178825Sdfr            const gss_OID desired_object,
224178825Sdfr            const gss_buffer_t value)
225178825Sdfr{
226178825Sdfr    krb5_context context;
227178825Sdfr
228178825Sdfr    GSSAPI_KRB5_INIT (&context);
229178825Sdfr
230178825Sdfr    if (value == GSS_C_NO_BUFFER) {
231178825Sdfr	*minor_status = EINVAL;
232178825Sdfr	return GSS_S_FAILURE;
233178825Sdfr    }
234178825Sdfr
235178825Sdfr    if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_CRED_X))
236178825Sdfr	return import_cred(minor_status, context, cred_handle, value);
237178825Sdfr
238178825Sdfr    if (gss_oid_equal(desired_object, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X))
239178825Sdfr	return allowed_enctypes(minor_status, context, cred_handle, value);
240178825Sdfr
241233294Sstas    if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_CI_FLAGS_X)) {
242233294Sstas	return no_ci_flags(minor_status, context, cred_handle, value);
243233294Sstas    }
244233294Sstas
245233294Sstas
246178825Sdfr    *minor_status = EINVAL;
247178825Sdfr    return GSS_S_FAILURE;
248178825Sdfr}
249