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 "spnego_locl.h"
34178825Sdfr
35233294SstasOM_uint32 GSSAPI_CALLCONV
36178825Sdfr_gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle)
37178825Sdfr{
38178825Sdfr    OM_uint32 ret;
39233294Sstas
40178825Sdfr    *minor_status = 0;
41178825Sdfr
42233294Sstas    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL)
43178825Sdfr	return GSS_S_COMPLETE;
44178825Sdfr
45233294Sstas    ret = gss_release_cred(minor_status, cred_handle);
46178825Sdfr
47178825Sdfr    *cred_handle = GSS_C_NO_CREDENTIAL;
48178825Sdfr
49178825Sdfr    return ret;
50178825Sdfr}
51178825Sdfr
52178825Sdfr/*
53178825Sdfr * For now, just a simple wrapper that avoids recursion. When
54178825Sdfr * we support gss_{get,set}_neg_mechs() we will need to expose
55178825Sdfr * more functionality.
56178825Sdfr */
57233294SstasOM_uint32 GSSAPI_CALLCONV _gss_spnego_acquire_cred
58178825Sdfr(OM_uint32 *minor_status,
59178825Sdfr const gss_name_t desired_name,
60178825Sdfr OM_uint32 time_req,
61178825Sdfr const gss_OID_set desired_mechs,
62178825Sdfr gss_cred_usage_t cred_usage,
63178825Sdfr gss_cred_id_t * output_cred_handle,
64178825Sdfr gss_OID_set * actual_mechs,
65178825Sdfr OM_uint32 * time_rec
66178825Sdfr    )
67178825Sdfr{
68178825Sdfr    const spnego_name dname = (const spnego_name)desired_name;
69178825Sdfr    gss_name_t name = GSS_C_NO_NAME;
70178825Sdfr    OM_uint32 ret, tmp;
71178825Sdfr    gss_OID_set_desc actual_desired_mechs;
72178825Sdfr    gss_OID_set mechs;
73233294Sstas    size_t i, j;
74178825Sdfr
75178825Sdfr    *output_cred_handle = GSS_C_NO_CREDENTIAL;
76178825Sdfr
77178825Sdfr    if (dname) {
78178825Sdfr	ret = gss_import_name(minor_status, &dname->value, &dname->type, &name);
79178825Sdfr	if (ret) {
80178825Sdfr	    return ret;
81178825Sdfr	}
82178825Sdfr    }
83233294Sstas
84178825Sdfr    ret = gss_indicate_mechs(minor_status, &mechs);
85178825Sdfr    if (ret != GSS_S_COMPLETE) {
86178825Sdfr	gss_release_name(minor_status, &name);
87178825Sdfr	return ret;
88178825Sdfr    }
89178825Sdfr
90178825Sdfr    /* Remove ourselves from this list */
91178825Sdfr    actual_desired_mechs.count = mechs->count;
92178825Sdfr    actual_desired_mechs.elements = malloc(actual_desired_mechs.count *
93178825Sdfr					   sizeof(gss_OID_desc));
94178825Sdfr    if (actual_desired_mechs.elements == NULL) {
95178825Sdfr	*minor_status = ENOMEM;
96178825Sdfr	ret = GSS_S_FAILURE;
97178825Sdfr	goto out;
98178825Sdfr    }
99178825Sdfr
100178825Sdfr    for (i = 0, j = 0; i < mechs->count; i++) {
101178825Sdfr	if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM))
102178825Sdfr	    continue;
103178825Sdfr
104178825Sdfr	actual_desired_mechs.elements[j] = mechs->elements[i];
105178825Sdfr	j++;
106178825Sdfr    }
107178825Sdfr    actual_desired_mechs.count = j;
108178825Sdfr
109178825Sdfr    ret = gss_acquire_cred(minor_status, name,
110178825Sdfr			   time_req, &actual_desired_mechs,
111178825Sdfr			   cred_usage,
112233294Sstas			   output_cred_handle,
113178825Sdfr			   actual_mechs, time_rec);
114178825Sdfr    if (ret != GSS_S_COMPLETE)
115178825Sdfr	goto out;
116178825Sdfr
117178825Sdfrout:
118178825Sdfr    gss_release_name(minor_status, &name);
119178825Sdfr    gss_release_oid_set(&tmp, &mechs);
120178825Sdfr    if (actual_desired_mechs.elements != NULL) {
121178825Sdfr	free(actual_desired_mechs.elements);
122178825Sdfr    }
123178825Sdfr    if (ret != GSS_S_COMPLETE) {
124233294Sstas	_gss_spnego_release_cred(&tmp, output_cred_handle);
125178825Sdfr    }
126178825Sdfr
127178825Sdfr    return ret;
128178825Sdfr}
129178825Sdfr
130233294SstasOM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_cred
131178825Sdfr           (OM_uint32 * minor_status,
132178825Sdfr            const gss_cred_id_t cred_handle,
133178825Sdfr            gss_name_t * name,
134178825Sdfr            OM_uint32 * lifetime,
135178825Sdfr            gss_cred_usage_t * cred_usage,
136178825Sdfr            gss_OID_set * mechanisms
137178825Sdfr           )
138178825Sdfr{
139178825Sdfr    spnego_name sname = NULL;
140178825Sdfr    OM_uint32 ret;
141178825Sdfr
142178825Sdfr    if (cred_handle == GSS_C_NO_CREDENTIAL) {
143178825Sdfr	*minor_status = 0;
144178825Sdfr	return GSS_S_NO_CRED;
145178825Sdfr    }
146178825Sdfr
147178825Sdfr    if (name) {
148178825Sdfr	sname = calloc(1, sizeof(*sname));
149178825Sdfr	if (sname == NULL) {
150178825Sdfr	    *minor_status = ENOMEM;
151178825Sdfr	    return GSS_S_FAILURE;
152178825Sdfr	}
153178825Sdfr    }
154178825Sdfr
155178825Sdfr    ret = gss_inquire_cred(minor_status,
156233294Sstas			   cred_handle,
157178825Sdfr			   sname ? &sname->mech : NULL,
158178825Sdfr			   lifetime,
159178825Sdfr			   cred_usage,
160178825Sdfr			   mechanisms);
161178825Sdfr    if (ret) {
162178825Sdfr	if (sname)
163178825Sdfr	    free(sname);
164178825Sdfr	return ret;
165178825Sdfr    }
166178825Sdfr    if (name)
167178825Sdfr	*name = (gss_name_t)sname;
168178825Sdfr
169178825Sdfr    return ret;
170178825Sdfr}
171178825Sdfr
172233294SstasOM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_cred_by_mech (
173178825Sdfr            OM_uint32 * minor_status,
174178825Sdfr            const gss_cred_id_t cred_handle,
175178825Sdfr            const gss_OID mech_type,
176178825Sdfr            gss_name_t * name,
177178825Sdfr            OM_uint32 * initiator_lifetime,
178178825Sdfr            OM_uint32 * acceptor_lifetime,
179178825Sdfr            gss_cred_usage_t * cred_usage
180178825Sdfr           )
181178825Sdfr{
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    ret = gss_inquire_cred_by_mech(minor_status,
199233294Sstas				   cred_handle,
200178825Sdfr				   mech_type,
201178825Sdfr				   sname ? &sname->mech : NULL,
202178825Sdfr				   initiator_lifetime,
203178825Sdfr				   acceptor_lifetime,
204178825Sdfr				   cred_usage);
205178825Sdfr
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 GSS_S_COMPLETE;
215178825Sdfr}
216178825Sdfr
217233294SstasOM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_cred_by_oid
218178825Sdfr           (OM_uint32 * minor_status,
219178825Sdfr            const gss_cred_id_t cred_handle,
220178825Sdfr            const gss_OID desired_object,
221178825Sdfr            gss_buffer_set_t *data_set)
222178825Sdfr{
223178825Sdfr    OM_uint32 ret;
224178825Sdfr
225178825Sdfr    if (cred_handle == GSS_C_NO_CREDENTIAL) {
226178825Sdfr	*minor_status = 0;
227178825Sdfr	return GSS_S_NO_CRED;
228178825Sdfr    }
229178825Sdfr
230178825Sdfr    ret = gss_inquire_cred_by_oid(minor_status,
231233294Sstas				  cred_handle,
232178825Sdfr				  desired_object,
233178825Sdfr				  data_set);
234178825Sdfr
235178825Sdfr    return ret;
236178825Sdfr}
237178825Sdfr
238233294SstasOM_uint32 GSSAPI_CALLCONV
239233294Sstas_gss_spnego_set_cred_option (OM_uint32 *minor_status,
240233294Sstas			     gss_cred_id_t *cred_handle,
241233294Sstas			     const gss_OID object,
242233294Sstas			     const gss_buffer_t value)
243233294Sstas{
244233294Sstas    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
245233294Sstas	*minor_status = 0;
246233294Sstas	return GSS_S_NO_CRED;
247233294Sstas    }
248233294Sstas
249233294Sstas    return gss_set_cred_option(minor_status,
250233294Sstas			      cred_handle,
251233294Sstas			      object,
252233294Sstas			      value);
253233294Sstas}
254233294Sstas
255233294Sstas#if 0
256233294Sstas
257233294SstasOM_uint32 GSSAPI_CALLCONV
258233294Sstas_gss_spnego_export_cred (OM_uint32 *minor_status,
259233294Sstas			 gss_cred_id_t cred_handle,
260233294Sstas			 gss_buffer_t value)
261233294Sstas{
262233294Sstas    return gss_export_cred(minor_status, cred_handle, value);
263233294Sstas}
264233294Sstas
265233294SstasOM_uint32 GSSAPI_CALLCONV
266233294Sstas_gss_spnego_import_cred (OM_uint32 *minor_status,
267233294Sstas			 gss_buffer_t value,
268233294Sstas			 gss_cred_id_t *cred_handle)
269233294Sstas{
270233294Sstas    return gss_import_cred(minor_status, value, cred_handle);
271233294Sstas}
272233294Sstas
273233294Sstas#endif
274