1/*	$NetBSD: set_cred_option.c,v 1.2 2017/01/28 21:31:46 christos Exp $	*/
2
3/*
4 * Copyright (c) 2004, PADL Software Pty Ltd.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * 3. Neither the name of PADL Software nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include "gsskrb5_locl.h"
36
37static OM_uint32
38import_cred(OM_uint32 *minor_status,
39	    krb5_context context,
40            gss_cred_id_t *cred_handle,
41            const gss_buffer_t value)
42{
43    OM_uint32 major_stat;
44    krb5_error_code ret;
45    krb5_principal keytab_principal = NULL;
46    krb5_keytab keytab = NULL;
47    krb5_storage *sp = NULL;
48    krb5_ccache id = NULL;
49    char *str;
50
51    if (cred_handle == NULL || *cred_handle != GSS_C_NO_CREDENTIAL) {
52	*minor_status = 0;
53	return GSS_S_FAILURE;
54    }
55
56    sp = krb5_storage_from_mem(value->value, value->length);
57    if (sp == NULL) {
58	*minor_status = 0;
59	return GSS_S_FAILURE;
60    }
61
62    /* credential cache name */
63    ret = krb5_ret_string(sp, &str);
64    if (ret) {
65	*minor_status = ret;
66	major_stat =  GSS_S_FAILURE;
67	goto out;
68    }
69    if (str[0]) {
70	ret = krb5_cc_resolve(context, str, &id);
71	if (ret) {
72	    *minor_status = ret;
73	    major_stat =  GSS_S_FAILURE;
74	    goto out;
75	}
76    }
77    free(str);
78    str = NULL;
79
80    /* keytab principal name */
81    ret = krb5_ret_string(sp, &str);
82    if (ret == 0 && str[0])
83	ret = krb5_parse_name(context, str, &keytab_principal);
84    if (ret) {
85	*minor_status = ret;
86	major_stat = GSS_S_FAILURE;
87	goto out;
88    }
89    free(str);
90    str = NULL;
91
92    /* keytab principal */
93    ret = krb5_ret_string(sp, &str);
94    if (ret) {
95	*minor_status = ret;
96	major_stat =  GSS_S_FAILURE;
97	goto out;
98    }
99    if (str[0]) {
100	ret = krb5_kt_resolve(context, str, &keytab);
101	if (ret) {
102	    *minor_status = ret;
103	    major_stat =  GSS_S_FAILURE;
104	    goto out;
105	}
106    }
107    free(str);
108    str = NULL;
109
110    major_stat = _gsskrb5_krb5_import_cred(minor_status, id, keytab_principal,
111					   keytab, cred_handle);
112out:
113    if (id)
114	krb5_cc_close(context, id);
115    if (keytab_principal)
116	krb5_free_principal(context, keytab_principal);
117    if (keytab)
118	krb5_kt_close(context, keytab);
119    if (str)
120	free(str);
121    if (sp)
122	krb5_storage_free(sp);
123
124    return major_stat;
125}
126
127
128static OM_uint32
129allowed_enctypes(OM_uint32 *minor_status,
130		 krb5_context context,
131		 gss_cred_id_t *cred_handle,
132		 const gss_buffer_t value)
133{
134    OM_uint32 major_stat;
135    krb5_error_code ret;
136    size_t len, i;
137    krb5_enctype *enctypes = NULL;
138    krb5_storage *sp = NULL;
139    gsskrb5_cred cred;
140
141    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
142	*minor_status = 0;
143	return GSS_S_FAILURE;
144    }
145
146    cred = (gsskrb5_cred)*cred_handle;
147
148    if ((value->length % 4) != 0) {
149	*minor_status = 0;
150	major_stat = GSS_S_FAILURE;
151	goto out;
152    }
153
154    len = value->length / 4;
155    enctypes = malloc((len + 1) * 4);
156    if (enctypes == NULL) {
157	*minor_status = ENOMEM;
158	major_stat = GSS_S_FAILURE;
159	goto out;
160    }
161
162    sp = krb5_storage_from_mem(value->value, value->length);
163    if (sp == NULL) {
164	*minor_status = ENOMEM;
165	major_stat = GSS_S_FAILURE;
166	goto out;
167    }
168
169    for (i = 0; i < len; i++) {
170	uint32_t e;
171
172	ret = krb5_ret_uint32(sp, &e);
173	if (ret) {
174	    *minor_status = ret;
175	    major_stat =  GSS_S_FAILURE;
176	    goto out;
177	}
178	enctypes[i] = e;
179    }
180    enctypes[i] = 0;
181
182    if (cred->enctypes)
183	free(cred->enctypes);
184    cred->enctypes = enctypes;
185
186    krb5_storage_free(sp);
187
188    return GSS_S_COMPLETE;
189
190out:
191    if (sp)
192	krb5_storage_free(sp);
193    if (enctypes)
194	free(enctypes);
195
196    return major_stat;
197}
198
199static OM_uint32
200no_ci_flags(OM_uint32 *minor_status,
201	    krb5_context context,
202	    gss_cred_id_t *cred_handle,
203	    const gss_buffer_t value)
204{
205    gsskrb5_cred cred;
206
207    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
208	*minor_status = 0;
209	return GSS_S_FAILURE;
210    }
211
212    cred = (gsskrb5_cred)*cred_handle;
213    cred->cred_flags |= GSS_CF_NO_CI_FLAGS;
214
215    *minor_status = 0;
216    return GSS_S_COMPLETE;
217
218}
219
220
221OM_uint32 GSSAPI_CALLCONV
222_gsskrb5_set_cred_option
223           (OM_uint32 *minor_status,
224            gss_cred_id_t *cred_handle,
225            const gss_OID desired_object,
226            const gss_buffer_t value)
227{
228    krb5_context context;
229
230    GSSAPI_KRB5_INIT (&context);
231
232    if (value == GSS_C_NO_BUFFER) {
233	*minor_status = EINVAL;
234	return GSS_S_FAILURE;
235    }
236
237    if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_CRED_X))
238	return import_cred(minor_status, context, cred_handle, value);
239
240    if (gss_oid_equal(desired_object, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X))
241	return allowed_enctypes(minor_status, context, cred_handle, value);
242
243    if (gss_oid_equal(desired_object, GSS_KRB5_CRED_NO_CI_FLAGS_X)) {
244	return no_ci_flags(minor_status, context, cred_handle, value);
245    }
246
247
248    *minor_status = EINVAL;
249    return GSS_S_FAILURE;
250}
251