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
33178825Sdfr#include "spnego/spnego_locl.h"
34178825Sdfr
35178825SdfrRCSID("$Id: cred_stubs.c 20619 2007-05-08 13:43:45Z lha $");
36178825Sdfr
37178825SdfrOM_uint32
38178825Sdfr_gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle)
39178825Sdfr{
40178825Sdfr    gssspnego_cred cred;
41178825Sdfr    OM_uint32 ret;
42178825Sdfr
43178825Sdfr    *minor_status = 0;
44178825Sdfr
45178825Sdfr    if (*cred_handle == GSS_C_NO_CREDENTIAL) {
46178825Sdfr	return GSS_S_COMPLETE;
47178825Sdfr    }
48178825Sdfr    cred = (gssspnego_cred)*cred_handle;
49178825Sdfr
50178825Sdfr    ret = gss_release_cred(minor_status, &cred->negotiated_cred_id);
51178825Sdfr
52178825Sdfr    free(cred);
53178825Sdfr    *cred_handle = GSS_C_NO_CREDENTIAL;
54178825Sdfr
55178825Sdfr    return ret;
56178825Sdfr}
57178825Sdfr
58178825SdfrOM_uint32
59178825Sdfr_gss_spnego_alloc_cred(OM_uint32 *minor_status,
60178825Sdfr		       gss_cred_id_t mech_cred_handle,
61178825Sdfr		       gss_cred_id_t *cred_handle)
62178825Sdfr{
63178825Sdfr    gssspnego_cred cred;
64178825Sdfr
65178825Sdfr    if (*cred_handle != GSS_C_NO_CREDENTIAL) {
66178825Sdfr	*minor_status = EINVAL;
67178825Sdfr	return GSS_S_FAILURE;
68178825Sdfr    }
69178825Sdfr
70178825Sdfr    cred = calloc(1, sizeof(*cred));
71178825Sdfr    if (cred == NULL) {
72178825Sdfr	*cred_handle = GSS_C_NO_CREDENTIAL;
73178825Sdfr	*minor_status = ENOMEM;
74178825Sdfr	return GSS_S_FAILURE;
75178825Sdfr    }
76178825Sdfr
77178825Sdfr    cred->negotiated_cred_id = mech_cred_handle;
78178825Sdfr
79178825Sdfr    *cred_handle = (gss_cred_id_t)cred;
80178825Sdfr
81178825Sdfr    return GSS_S_COMPLETE;
82178825Sdfr}
83178825Sdfr
84178825Sdfr/*
85178825Sdfr * For now, just a simple wrapper that avoids recursion. When
86178825Sdfr * we support gss_{get,set}_neg_mechs() we will need to expose
87178825Sdfr * more functionality.
88178825Sdfr */
89178825SdfrOM_uint32 _gss_spnego_acquire_cred
90178825Sdfr(OM_uint32 *minor_status,
91178825Sdfr const gss_name_t desired_name,
92178825Sdfr OM_uint32 time_req,
93178825Sdfr const gss_OID_set desired_mechs,
94178825Sdfr gss_cred_usage_t cred_usage,
95178825Sdfr gss_cred_id_t * output_cred_handle,
96178825Sdfr gss_OID_set * actual_mechs,
97178825Sdfr OM_uint32 * time_rec
98178825Sdfr    )
99178825Sdfr{
100178825Sdfr    const spnego_name dname = (const spnego_name)desired_name;
101178825Sdfr    gss_name_t name = GSS_C_NO_NAME;
102178825Sdfr    OM_uint32 ret, tmp;
103178825Sdfr    gss_OID_set_desc actual_desired_mechs;
104178825Sdfr    gss_OID_set mechs;
105178825Sdfr    int i, j;
106178825Sdfr    gss_cred_id_t cred_handle = GSS_C_NO_CREDENTIAL;
107178825Sdfr    gssspnego_cred cred;
108178825Sdfr
109178825Sdfr    *output_cred_handle = GSS_C_NO_CREDENTIAL;
110178825Sdfr
111178825Sdfr    if (dname) {
112178825Sdfr	ret = gss_import_name(minor_status, &dname->value, &dname->type, &name);
113178825Sdfr	if (ret) {
114178825Sdfr	    return ret;
115178825Sdfr	}
116178825Sdfr    }
117178825Sdfr
118178825Sdfr    ret = gss_indicate_mechs(minor_status, &mechs);
119178825Sdfr    if (ret != GSS_S_COMPLETE) {
120178825Sdfr	gss_release_name(minor_status, &name);
121178825Sdfr	return ret;
122178825Sdfr    }
123178825Sdfr
124178825Sdfr    /* Remove ourselves from this list */
125178825Sdfr    actual_desired_mechs.count = mechs->count;
126178825Sdfr    actual_desired_mechs.elements = malloc(actual_desired_mechs.count *
127178825Sdfr					   sizeof(gss_OID_desc));
128178825Sdfr    if (actual_desired_mechs.elements == NULL) {
129178825Sdfr	*minor_status = ENOMEM;
130178825Sdfr	ret = GSS_S_FAILURE;
131178825Sdfr	goto out;
132178825Sdfr    }
133178825Sdfr
134178825Sdfr    for (i = 0, j = 0; i < mechs->count; i++) {
135178825Sdfr	if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM))
136178825Sdfr	    continue;
137178825Sdfr
138178825Sdfr	actual_desired_mechs.elements[j] = mechs->elements[i];
139178825Sdfr	j++;
140178825Sdfr    }
141178825Sdfr    actual_desired_mechs.count = j;
142178825Sdfr
143178825Sdfr    ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL,
144178825Sdfr				 &cred_handle);
145178825Sdfr    if (ret != GSS_S_COMPLETE)
146178825Sdfr	goto out;
147178825Sdfr
148178825Sdfr    cred = (gssspnego_cred)cred_handle;
149178825Sdfr    ret = gss_acquire_cred(minor_status, name,
150178825Sdfr			   time_req, &actual_desired_mechs,
151178825Sdfr			   cred_usage,
152178825Sdfr			   &cred->negotiated_cred_id,
153178825Sdfr			   actual_mechs, time_rec);
154178825Sdfr    if (ret != GSS_S_COMPLETE)
155178825Sdfr	goto out;
156178825Sdfr
157178825Sdfr    *output_cred_handle = cred_handle;
158178825Sdfr
159178825Sdfrout:
160178825Sdfr    gss_release_name(minor_status, &name);
161178825Sdfr    gss_release_oid_set(&tmp, &mechs);
162178825Sdfr    if (actual_desired_mechs.elements != NULL) {
163178825Sdfr	free(actual_desired_mechs.elements);
164178825Sdfr    }
165178825Sdfr    if (ret != GSS_S_COMPLETE) {
166178825Sdfr	_gss_spnego_release_cred(&tmp, &cred_handle);
167178825Sdfr    }
168178825Sdfr
169178825Sdfr    return ret;
170178825Sdfr}
171178825Sdfr
172178825SdfrOM_uint32 _gss_spnego_inquire_cred
173178825Sdfr           (OM_uint32 * minor_status,
174178825Sdfr            const gss_cred_id_t cred_handle,
175178825Sdfr            gss_name_t * name,
176178825Sdfr            OM_uint32 * lifetime,
177178825Sdfr            gss_cred_usage_t * cred_usage,
178178825Sdfr            gss_OID_set * mechanisms
179178825Sdfr           )
180178825Sdfr{
181178825Sdfr    gssspnego_cred cred;
182178825Sdfr    spnego_name sname = NULL;
183178825Sdfr    OM_uint32 ret;
184178825Sdfr
185178825Sdfr    if (cred_handle == GSS_C_NO_CREDENTIAL) {
186178825Sdfr	*minor_status = 0;
187178825Sdfr	return GSS_S_NO_CRED;
188178825Sdfr    }
189178825Sdfr
190178825Sdfr    if (name) {
191178825Sdfr	sname = calloc(1, sizeof(*sname));
192178825Sdfr	if (sname == NULL) {
193178825Sdfr	    *minor_status = ENOMEM;
194178825Sdfr	    return GSS_S_FAILURE;
195178825Sdfr	}
196178825Sdfr    }
197178825Sdfr
198178825Sdfr    cred = (gssspnego_cred)cred_handle;
199178825Sdfr
200178825Sdfr    ret = gss_inquire_cred(minor_status,
201178825Sdfr			   cred->negotiated_cred_id,
202178825Sdfr			   sname ? &sname->mech : NULL,
203178825Sdfr			   lifetime,
204178825Sdfr			   cred_usage,
205178825Sdfr			   mechanisms);
206178825Sdfr    if (ret) {
207178825Sdfr	if (sname)
208178825Sdfr	    free(sname);
209178825Sdfr	return ret;
210178825Sdfr    }
211178825Sdfr    if (name)
212178825Sdfr	*name = (gss_name_t)sname;
213178825Sdfr
214178825Sdfr    return ret;
215178825Sdfr}
216178825Sdfr
217178825SdfrOM_uint32 _gss_spnego_add_cred (
218178825Sdfr            OM_uint32 * minor_status,
219178825Sdfr            const gss_cred_id_t input_cred_handle,
220178825Sdfr            const gss_name_t desired_name,
221178825Sdfr            const gss_OID desired_mech,
222178825Sdfr            gss_cred_usage_t cred_usage,
223178825Sdfr            OM_uint32 initiator_time_req,
224178825Sdfr            OM_uint32 acceptor_time_req,
225178825Sdfr            gss_cred_id_t * output_cred_handle,
226178825Sdfr            gss_OID_set * actual_mechs,
227178825Sdfr            OM_uint32 * initiator_time_rec,
228178825Sdfr            OM_uint32 * acceptor_time_rec
229178825Sdfr           )
230178825Sdfr{
231178825Sdfr    gss_cred_id_t spnego_output_cred_handle = GSS_C_NO_CREDENTIAL;
232178825Sdfr    OM_uint32 ret, tmp;
233178825Sdfr    gssspnego_cred input_cred, output_cred;
234178825Sdfr
235178825Sdfr    *output_cred_handle = GSS_C_NO_CREDENTIAL;
236178825Sdfr
237178825Sdfr    ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL,
238178825Sdfr				 &spnego_output_cred_handle);
239178825Sdfr    if (ret)
240178825Sdfr	return ret;
241178825Sdfr
242178825Sdfr    input_cred = (gssspnego_cred)input_cred_handle;
243178825Sdfr    output_cred = (gssspnego_cred)spnego_output_cred_handle;
244178825Sdfr
245178825Sdfr    ret = gss_add_cred(minor_status,
246178825Sdfr		       input_cred->negotiated_cred_id,
247178825Sdfr		       desired_name,
248178825Sdfr		       desired_mech,
249178825Sdfr		       cred_usage,
250178825Sdfr		       initiator_time_req,
251178825Sdfr		       acceptor_time_req,
252178825Sdfr		       &output_cred->negotiated_cred_id,
253178825Sdfr		       actual_mechs,
254178825Sdfr		       initiator_time_rec,
255178825Sdfr		       acceptor_time_rec);
256178825Sdfr    if (ret) {
257178825Sdfr	_gss_spnego_release_cred(&tmp, &spnego_output_cred_handle);
258178825Sdfr	return ret;
259178825Sdfr    }
260178825Sdfr
261178825Sdfr    *output_cred_handle = spnego_output_cred_handle;
262178825Sdfr
263178825Sdfr    return GSS_S_COMPLETE;
264178825Sdfr}
265178825Sdfr
266178825SdfrOM_uint32 _gss_spnego_inquire_cred_by_mech (
267178825Sdfr            OM_uint32 * minor_status,
268178825Sdfr            const gss_cred_id_t cred_handle,
269178825Sdfr            const gss_OID mech_type,
270178825Sdfr            gss_name_t * name,
271178825Sdfr            OM_uint32 * initiator_lifetime,
272178825Sdfr            OM_uint32 * acceptor_lifetime,
273178825Sdfr            gss_cred_usage_t * cred_usage
274178825Sdfr           )
275178825Sdfr{
276178825Sdfr    gssspnego_cred cred;
277178825Sdfr    spnego_name sname = NULL;
278178825Sdfr    OM_uint32 ret;
279178825Sdfr
280178825Sdfr    if (cred_handle == GSS_C_NO_CREDENTIAL) {
281178825Sdfr	*minor_status = 0;
282178825Sdfr	return GSS_S_NO_CRED;
283178825Sdfr    }
284178825Sdfr
285178825Sdfr    if (name) {
286178825Sdfr	sname = calloc(1, sizeof(*sname));
287178825Sdfr	if (sname == NULL) {
288178825Sdfr	    *minor_status = ENOMEM;
289178825Sdfr	    return GSS_S_FAILURE;
290178825Sdfr	}
291178825Sdfr    }
292178825Sdfr
293178825Sdfr    cred = (gssspnego_cred)cred_handle;
294178825Sdfr
295178825Sdfr    ret = gss_inquire_cred_by_mech(minor_status,
296178825Sdfr				   cred->negotiated_cred_id,
297178825Sdfr				   mech_type,
298178825Sdfr				   sname ? &sname->mech : NULL,
299178825Sdfr				   initiator_lifetime,
300178825Sdfr				   acceptor_lifetime,
301178825Sdfr				   cred_usage);
302178825Sdfr
303178825Sdfr    if (ret) {
304178825Sdfr	if (sname)
305178825Sdfr	    free(sname);
306178825Sdfr	return ret;
307178825Sdfr    }
308178825Sdfr    if (name)
309178825Sdfr	*name = (gss_name_t)sname;
310178825Sdfr
311178825Sdfr    return GSS_S_COMPLETE;
312178825Sdfr}
313178825Sdfr
314178825SdfrOM_uint32 _gss_spnego_inquire_cred_by_oid
315178825Sdfr           (OM_uint32 * minor_status,
316178825Sdfr            const gss_cred_id_t cred_handle,
317178825Sdfr            const gss_OID desired_object,
318178825Sdfr            gss_buffer_set_t *data_set)
319178825Sdfr{
320178825Sdfr    gssspnego_cred cred;
321178825Sdfr    OM_uint32 ret;
322178825Sdfr
323178825Sdfr    if (cred_handle == GSS_C_NO_CREDENTIAL) {
324178825Sdfr	*minor_status = 0;
325178825Sdfr	return GSS_S_NO_CRED;
326178825Sdfr    }
327178825Sdfr    cred = (gssspnego_cred)cred_handle;
328178825Sdfr
329178825Sdfr    ret = gss_inquire_cred_by_oid(minor_status,
330178825Sdfr				  cred->negotiated_cred_id,
331178825Sdfr				  desired_object,
332178825Sdfr				  data_set);
333178825Sdfr
334178825Sdfr    return ret;
335178825Sdfr}
336178825Sdfr
337