cred_stubs.c revision 178826
1/*
2 * Copyright (c) 2004, PADL Software Pty Ltd.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * 3. Neither the name of PADL Software nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include "spnego/spnego_locl.h"
34
35RCSID("$Id: cred_stubs.c 20619 2007-05-08 13:43:45Z lha $");
36
37OM_uint32
38_gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle)
39{
40    gssspnego_cred cred;
41    OM_uint32 ret;
42
43    *minor_status = 0;
44
45    if (*cred_handle == GSS_C_NO_CREDENTIAL) {
46	return GSS_S_COMPLETE;
47    }
48    cred = (gssspnego_cred)*cred_handle;
49
50    ret = gss_release_cred(minor_status, &cred->negotiated_cred_id);
51
52    free(cred);
53    *cred_handle = GSS_C_NO_CREDENTIAL;
54
55    return ret;
56}
57
58OM_uint32
59_gss_spnego_alloc_cred(OM_uint32 *minor_status,
60		       gss_cred_id_t mech_cred_handle,
61		       gss_cred_id_t *cred_handle)
62{
63    gssspnego_cred cred;
64
65    if (*cred_handle != GSS_C_NO_CREDENTIAL) {
66	*minor_status = EINVAL;
67	return GSS_S_FAILURE;
68    }
69
70    cred = calloc(1, sizeof(*cred));
71    if (cred == NULL) {
72	*cred_handle = GSS_C_NO_CREDENTIAL;
73	*minor_status = ENOMEM;
74	return GSS_S_FAILURE;
75    }
76
77    cred->negotiated_cred_id = mech_cred_handle;
78
79    *cred_handle = (gss_cred_id_t)cred;
80
81    return GSS_S_COMPLETE;
82}
83
84/*
85 * For now, just a simple wrapper that avoids recursion. When
86 * we support gss_{get,set}_neg_mechs() we will need to expose
87 * more functionality.
88 */
89OM_uint32 _gss_spnego_acquire_cred
90(OM_uint32 *minor_status,
91 const gss_name_t desired_name,
92 OM_uint32 time_req,
93 const gss_OID_set desired_mechs,
94 gss_cred_usage_t cred_usage,
95 gss_cred_id_t * output_cred_handle,
96 gss_OID_set * actual_mechs,
97 OM_uint32 * time_rec
98    )
99{
100    const spnego_name dname = (const spnego_name)desired_name;
101    gss_name_t name = GSS_C_NO_NAME;
102    OM_uint32 ret, tmp;
103    gss_OID_set_desc actual_desired_mechs;
104    gss_OID_set mechs;
105    int i, j;
106    gss_cred_id_t cred_handle = GSS_C_NO_CREDENTIAL;
107    gssspnego_cred cred;
108
109    *output_cred_handle = GSS_C_NO_CREDENTIAL;
110
111    if (dname) {
112	ret = gss_import_name(minor_status, &dname->value, &dname->type, &name);
113	if (ret) {
114	    return ret;
115	}
116    }
117
118    ret = gss_indicate_mechs(minor_status, &mechs);
119    if (ret != GSS_S_COMPLETE) {
120	gss_release_name(minor_status, &name);
121	return ret;
122    }
123
124    /* Remove ourselves from this list */
125    actual_desired_mechs.count = mechs->count;
126    actual_desired_mechs.elements = malloc(actual_desired_mechs.count *
127					   sizeof(gss_OID_desc));
128    if (actual_desired_mechs.elements == NULL) {
129	*minor_status = ENOMEM;
130	ret = GSS_S_FAILURE;
131	goto out;
132    }
133
134    for (i = 0, j = 0; i < mechs->count; i++) {
135	if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM))
136	    continue;
137
138	actual_desired_mechs.elements[j] = mechs->elements[i];
139	j++;
140    }
141    actual_desired_mechs.count = j;
142
143    ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL,
144				 &cred_handle);
145    if (ret != GSS_S_COMPLETE)
146	goto out;
147
148    cred = (gssspnego_cred)cred_handle;
149    ret = gss_acquire_cred(minor_status, name,
150			   time_req, &actual_desired_mechs,
151			   cred_usage,
152			   &cred->negotiated_cred_id,
153			   actual_mechs, time_rec);
154    if (ret != GSS_S_COMPLETE)
155	goto out;
156
157    *output_cred_handle = cred_handle;
158
159out:
160    gss_release_name(minor_status, &name);
161    gss_release_oid_set(&tmp, &mechs);
162    if (actual_desired_mechs.elements != NULL) {
163	free(actual_desired_mechs.elements);
164    }
165    if (ret != GSS_S_COMPLETE) {
166	_gss_spnego_release_cred(&tmp, &cred_handle);
167    }
168
169    return ret;
170}
171
172OM_uint32 _gss_spnego_inquire_cred
173           (OM_uint32 * minor_status,
174            const gss_cred_id_t cred_handle,
175            gss_name_t * name,
176            OM_uint32 * lifetime,
177            gss_cred_usage_t * cred_usage,
178            gss_OID_set * mechanisms
179           )
180{
181    gssspnego_cred cred;
182    spnego_name sname = NULL;
183    OM_uint32 ret;
184
185    if (cred_handle == GSS_C_NO_CREDENTIAL) {
186	*minor_status = 0;
187	return GSS_S_NO_CRED;
188    }
189
190    if (name) {
191	sname = calloc(1, sizeof(*sname));
192	if (sname == NULL) {
193	    *minor_status = ENOMEM;
194	    return GSS_S_FAILURE;
195	}
196    }
197
198    cred = (gssspnego_cred)cred_handle;
199
200    ret = gss_inquire_cred(minor_status,
201			   cred->negotiated_cred_id,
202			   sname ? &sname->mech : NULL,
203			   lifetime,
204			   cred_usage,
205			   mechanisms);
206    if (ret) {
207	if (sname)
208	    free(sname);
209	return ret;
210    }
211    if (name)
212	*name = (gss_name_t)sname;
213
214    return ret;
215}
216
217OM_uint32 _gss_spnego_add_cred (
218            OM_uint32 * minor_status,
219            const gss_cred_id_t input_cred_handle,
220            const gss_name_t desired_name,
221            const gss_OID desired_mech,
222            gss_cred_usage_t cred_usage,
223            OM_uint32 initiator_time_req,
224            OM_uint32 acceptor_time_req,
225            gss_cred_id_t * output_cred_handle,
226            gss_OID_set * actual_mechs,
227            OM_uint32 * initiator_time_rec,
228            OM_uint32 * acceptor_time_rec
229           )
230{
231    gss_cred_id_t spnego_output_cred_handle = GSS_C_NO_CREDENTIAL;
232    OM_uint32 ret, tmp;
233    gssspnego_cred input_cred, output_cred;
234
235    *output_cred_handle = GSS_C_NO_CREDENTIAL;
236
237    ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL,
238				 &spnego_output_cred_handle);
239    if (ret)
240	return ret;
241
242    input_cred = (gssspnego_cred)input_cred_handle;
243    output_cred = (gssspnego_cred)spnego_output_cred_handle;
244
245    ret = gss_add_cred(minor_status,
246		       input_cred->negotiated_cred_id,
247		       desired_name,
248		       desired_mech,
249		       cred_usage,
250		       initiator_time_req,
251		       acceptor_time_req,
252		       &output_cred->negotiated_cred_id,
253		       actual_mechs,
254		       initiator_time_rec,
255		       acceptor_time_rec);
256    if (ret) {
257	_gss_spnego_release_cred(&tmp, &spnego_output_cred_handle);
258	return ret;
259    }
260
261    *output_cred_handle = spnego_output_cred_handle;
262
263    return GSS_S_COMPLETE;
264}
265
266OM_uint32 _gss_spnego_inquire_cred_by_mech (
267            OM_uint32 * minor_status,
268            const gss_cred_id_t cred_handle,
269            const gss_OID mech_type,
270            gss_name_t * name,
271            OM_uint32 * initiator_lifetime,
272            OM_uint32 * acceptor_lifetime,
273            gss_cred_usage_t * cred_usage
274           )
275{
276    gssspnego_cred cred;
277    spnego_name sname = NULL;
278    OM_uint32 ret;
279
280    if (cred_handle == GSS_C_NO_CREDENTIAL) {
281	*minor_status = 0;
282	return GSS_S_NO_CRED;
283    }
284
285    if (name) {
286	sname = calloc(1, sizeof(*sname));
287	if (sname == NULL) {
288	    *minor_status = ENOMEM;
289	    return GSS_S_FAILURE;
290	}
291    }
292
293    cred = (gssspnego_cred)cred_handle;
294
295    ret = gss_inquire_cred_by_mech(minor_status,
296				   cred->negotiated_cred_id,
297				   mech_type,
298				   sname ? &sname->mech : NULL,
299				   initiator_lifetime,
300				   acceptor_lifetime,
301				   cred_usage);
302
303    if (ret) {
304	if (sname)
305	    free(sname);
306	return ret;
307    }
308    if (name)
309	*name = (gss_name_t)sname;
310
311    return GSS_S_COMPLETE;
312}
313
314OM_uint32 _gss_spnego_inquire_cred_by_oid
315           (OM_uint32 * minor_status,
316            const gss_cred_id_t cred_handle,
317            const gss_OID desired_object,
318            gss_buffer_set_t *data_set)
319{
320    gssspnego_cred cred;
321    OM_uint32 ret;
322
323    if (cred_handle == GSS_C_NO_CREDENTIAL) {
324	*minor_status = 0;
325	return GSS_S_NO_CRED;
326    }
327    cred = (gssspnego_cred)cred_handle;
328
329    ret = gss_inquire_cred_by_oid(minor_status,
330				  cred->negotiated_cred_id,
331				  desired_object,
332				  data_set);
333
334    return ret;
335}
336
337