1*7f2fe78bSCy Schubert /* #pragma ident "@(#)g_acquire_cred.c 1.22 04/02/23 SMI" */
2*7f2fe78bSCy Schubert
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright 1996 by Sun Microsystems, Inc.
5*7f2fe78bSCy Schubert *
6*7f2fe78bSCy Schubert * Permission to use, copy, modify, distribute, and sell this software
7*7f2fe78bSCy Schubert * and its documentation for any purpose is hereby granted without fee,
8*7f2fe78bSCy Schubert * provided that the above copyright notice appears in all copies and
9*7f2fe78bSCy Schubert * that both that copyright notice and this permission notice appear in
10*7f2fe78bSCy Schubert * supporting documentation, and that the name of Sun Microsystems not be used
11*7f2fe78bSCy Schubert * in advertising or publicity pertaining to distribution of the software
12*7f2fe78bSCy Schubert * without specific, written prior permission. Sun Microsystems makes no
13*7f2fe78bSCy Schubert * representations about the suitability of this software for any
14*7f2fe78bSCy Schubert * purpose. It is provided "as is" without express or implied warranty.
15*7f2fe78bSCy Schubert *
16*7f2fe78bSCy Schubert * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17*7f2fe78bSCy Schubert * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18*7f2fe78bSCy Schubert * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19*7f2fe78bSCy Schubert * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20*7f2fe78bSCy Schubert * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21*7f2fe78bSCy Schubert * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22*7f2fe78bSCy Schubert * PERFORMANCE OF THIS SOFTWARE.
23*7f2fe78bSCy Schubert */
24*7f2fe78bSCy Schubert
25*7f2fe78bSCy Schubert /*
26*7f2fe78bSCy Schubert * glue routine for gss_acquire_cred
27*7f2fe78bSCy Schubert */
28*7f2fe78bSCy Schubert
29*7f2fe78bSCy Schubert #include "mglueP.h"
30*7f2fe78bSCy Schubert #include <stdio.h>
31*7f2fe78bSCy Schubert #ifdef HAVE_STDLIB_H
32*7f2fe78bSCy Schubert #include <stdlib.h>
33*7f2fe78bSCy Schubert #endif
34*7f2fe78bSCy Schubert #include <string.h>
35*7f2fe78bSCy Schubert #include <errno.h>
36*7f2fe78bSCy Schubert #include <time.h>
37*7f2fe78bSCy Schubert
38*7f2fe78bSCy Schubert static OM_uint32
val_acq_cred_args(OM_uint32 * minor_status,gss_name_t desired_name,OM_uint32 time_req,gss_OID_set desired_mechs,int cred_usage,gss_const_key_value_set_t cred_store,gss_cred_id_t * output_cred_handle,gss_OID_set * actual_mechs,OM_uint32 * time_rec)39*7f2fe78bSCy Schubert val_acq_cred_args(
40*7f2fe78bSCy Schubert OM_uint32 *minor_status,
41*7f2fe78bSCy Schubert gss_name_t desired_name,
42*7f2fe78bSCy Schubert OM_uint32 time_req,
43*7f2fe78bSCy Schubert gss_OID_set desired_mechs,
44*7f2fe78bSCy Schubert int cred_usage,
45*7f2fe78bSCy Schubert gss_const_key_value_set_t cred_store,
46*7f2fe78bSCy Schubert gss_cred_id_t *output_cred_handle,
47*7f2fe78bSCy Schubert gss_OID_set *actual_mechs,
48*7f2fe78bSCy Schubert OM_uint32 *time_rec)
49*7f2fe78bSCy Schubert {
50*7f2fe78bSCy Schubert
51*7f2fe78bSCy Schubert /* Initialize outputs. */
52*7f2fe78bSCy Schubert
53*7f2fe78bSCy Schubert if (minor_status != NULL)
54*7f2fe78bSCy Schubert *minor_status = 0;
55*7f2fe78bSCy Schubert
56*7f2fe78bSCy Schubert if (output_cred_handle != NULL)
57*7f2fe78bSCy Schubert *output_cred_handle = GSS_C_NO_CREDENTIAL;
58*7f2fe78bSCy Schubert
59*7f2fe78bSCy Schubert if (actual_mechs != NULL)
60*7f2fe78bSCy Schubert *actual_mechs = GSS_C_NULL_OID_SET;
61*7f2fe78bSCy Schubert
62*7f2fe78bSCy Schubert if (time_rec != NULL)
63*7f2fe78bSCy Schubert *time_rec = 0;
64*7f2fe78bSCy Schubert
65*7f2fe78bSCy Schubert /* Validate arguments. */
66*7f2fe78bSCy Schubert
67*7f2fe78bSCy Schubert if (minor_status == NULL)
68*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_WRITE);
69*7f2fe78bSCy Schubert
70*7f2fe78bSCy Schubert if (output_cred_handle == NULL)
71*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_WRITE);
72*7f2fe78bSCy Schubert
73*7f2fe78bSCy Schubert if (cred_usage != GSS_C_ACCEPT
74*7f2fe78bSCy Schubert && cred_usage != GSS_C_INITIATE
75*7f2fe78bSCy Schubert && cred_usage != GSS_C_BOTH) {
76*7f2fe78bSCy Schubert if (minor_status) {
77*7f2fe78bSCy Schubert *minor_status = EINVAL;
78*7f2fe78bSCy Schubert map_errcode(minor_status);
79*7f2fe78bSCy Schubert }
80*7f2fe78bSCy Schubert return GSS_S_FAILURE;
81*7f2fe78bSCy Schubert }
82*7f2fe78bSCy Schubert
83*7f2fe78bSCy Schubert return (GSS_S_COMPLETE);
84*7f2fe78bSCy Schubert }
85*7f2fe78bSCy Schubert
86*7f2fe78bSCy Schubert
87*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_acquire_cred(minor_status,desired_name,time_req,desired_mechs,cred_usage,output_cred_handle,actual_mechs,time_rec)88*7f2fe78bSCy Schubert gss_acquire_cred(minor_status,
89*7f2fe78bSCy Schubert desired_name,
90*7f2fe78bSCy Schubert time_req,
91*7f2fe78bSCy Schubert desired_mechs,
92*7f2fe78bSCy Schubert cred_usage,
93*7f2fe78bSCy Schubert output_cred_handle,
94*7f2fe78bSCy Schubert actual_mechs,
95*7f2fe78bSCy Schubert time_rec)
96*7f2fe78bSCy Schubert
97*7f2fe78bSCy Schubert OM_uint32 * minor_status;
98*7f2fe78bSCy Schubert gss_name_t desired_name;
99*7f2fe78bSCy Schubert OM_uint32 time_req;
100*7f2fe78bSCy Schubert gss_OID_set desired_mechs;
101*7f2fe78bSCy Schubert int cred_usage;
102*7f2fe78bSCy Schubert gss_cred_id_t * output_cred_handle;
103*7f2fe78bSCy Schubert gss_OID_set * actual_mechs;
104*7f2fe78bSCy Schubert OM_uint32 * time_rec;
105*7f2fe78bSCy Schubert
106*7f2fe78bSCy Schubert {
107*7f2fe78bSCy Schubert return gss_acquire_cred_from(minor_status, desired_name, time_req,
108*7f2fe78bSCy Schubert desired_mechs, cred_usage, NULL,
109*7f2fe78bSCy Schubert output_cred_handle, actual_mechs, time_rec);
110*7f2fe78bSCy Schubert }
111*7f2fe78bSCy Schubert
112*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_acquire_cred_from(minor_status,desired_name,time_req,desired_mechs,cred_usage,cred_store,output_cred_handle,actual_mechs,time_rec)113*7f2fe78bSCy Schubert gss_acquire_cred_from(minor_status,
114*7f2fe78bSCy Schubert desired_name,
115*7f2fe78bSCy Schubert time_req,
116*7f2fe78bSCy Schubert desired_mechs,
117*7f2fe78bSCy Schubert cred_usage,
118*7f2fe78bSCy Schubert cred_store,
119*7f2fe78bSCy Schubert output_cred_handle,
120*7f2fe78bSCy Schubert actual_mechs,
121*7f2fe78bSCy Schubert time_rec)
122*7f2fe78bSCy Schubert
123*7f2fe78bSCy Schubert OM_uint32 * minor_status;
124*7f2fe78bSCy Schubert gss_name_t desired_name;
125*7f2fe78bSCy Schubert OM_uint32 time_req;
126*7f2fe78bSCy Schubert gss_OID_set desired_mechs;
127*7f2fe78bSCy Schubert int cred_usage;
128*7f2fe78bSCy Schubert gss_const_key_value_set_t cred_store;
129*7f2fe78bSCy Schubert gss_cred_id_t * output_cred_handle;
130*7f2fe78bSCy Schubert gss_OID_set * actual_mechs;
131*7f2fe78bSCy Schubert OM_uint32 * time_rec;
132*7f2fe78bSCy Schubert
133*7f2fe78bSCy Schubert {
134*7f2fe78bSCy Schubert OM_uint32 major = GSS_S_FAILURE, tmpMinor;
135*7f2fe78bSCy Schubert OM_uint32 first_major = GSS_S_COMPLETE, first_minor = 0;
136*7f2fe78bSCy Schubert OM_uint32 initTimeOut = 0, acceptTimeOut = 0, outTime = GSS_C_INDEFINITE;
137*7f2fe78bSCy Schubert gss_OID_set mechs = GSS_C_NO_OID_SET;
138*7f2fe78bSCy Schubert gss_OID_set_desc except_attrs;
139*7f2fe78bSCy Schubert gss_OID_desc attr_oids[2];
140*7f2fe78bSCy Schubert unsigned int i;
141*7f2fe78bSCy Schubert gss_union_cred_t creds = NULL;
142*7f2fe78bSCy Schubert
143*7f2fe78bSCy Schubert major = val_acq_cred_args(minor_status,
144*7f2fe78bSCy Schubert desired_name,
145*7f2fe78bSCy Schubert time_req,
146*7f2fe78bSCy Schubert desired_mechs,
147*7f2fe78bSCy Schubert cred_usage,
148*7f2fe78bSCy Schubert cred_store,
149*7f2fe78bSCy Schubert output_cred_handle,
150*7f2fe78bSCy Schubert actual_mechs,
151*7f2fe78bSCy Schubert time_rec);
152*7f2fe78bSCy Schubert if (major != GSS_S_COMPLETE)
153*7f2fe78bSCy Schubert goto cleanup;
154*7f2fe78bSCy Schubert
155*7f2fe78bSCy Schubert /*
156*7f2fe78bSCy Schubert * if desired_mechs equals GSS_C_NULL_OID_SET, then try to
157*7f2fe78bSCy Schubert * acquire credentials for all non-deprecated mechanisms.
158*7f2fe78bSCy Schubert */
159*7f2fe78bSCy Schubert if (desired_mechs == GSS_C_NULL_OID_SET) {
160*7f2fe78bSCy Schubert attr_oids[0] = *GSS_C_MA_DEPRECATED;
161*7f2fe78bSCy Schubert attr_oids[1] = *GSS_C_MA_NOT_DFLT_MECH;
162*7f2fe78bSCy Schubert except_attrs.count = 2;
163*7f2fe78bSCy Schubert except_attrs.elements = attr_oids;
164*7f2fe78bSCy Schubert major = gss_indicate_mechs_by_attrs(minor_status, GSS_C_NO_OID_SET,
165*7f2fe78bSCy Schubert &except_attrs, GSS_C_NO_OID_SET,
166*7f2fe78bSCy Schubert &mechs);
167*7f2fe78bSCy Schubert if (major != GSS_S_COMPLETE)
168*7f2fe78bSCy Schubert goto cleanup;
169*7f2fe78bSCy Schubert } else
170*7f2fe78bSCy Schubert mechs = desired_mechs;
171*7f2fe78bSCy Schubert
172*7f2fe78bSCy Schubert if (mechs->count == 0) {
173*7f2fe78bSCy Schubert major = GSS_S_BAD_MECH;
174*7f2fe78bSCy Schubert goto cleanup;
175*7f2fe78bSCy Schubert }
176*7f2fe78bSCy Schubert
177*7f2fe78bSCy Schubert /* allocate the output credential structure */
178*7f2fe78bSCy Schubert creds = (gss_union_cred_t)calloc(1, sizeof (gss_union_cred_desc));
179*7f2fe78bSCy Schubert if (creds == NULL) {
180*7f2fe78bSCy Schubert major = GSS_S_FAILURE;
181*7f2fe78bSCy Schubert *minor_status = ENOMEM;
182*7f2fe78bSCy Schubert goto cleanup;
183*7f2fe78bSCy Schubert }
184*7f2fe78bSCy Schubert
185*7f2fe78bSCy Schubert creds->count = 0;
186*7f2fe78bSCy Schubert creds->loopback = creds;
187*7f2fe78bSCy Schubert
188*7f2fe78bSCy Schubert /* for each requested mech attempt to obtain a credential */
189*7f2fe78bSCy Schubert for (i = 0, major = GSS_S_UNAVAILABLE; i < mechs->count; i++) {
190*7f2fe78bSCy Schubert major = gss_add_cred_from(&tmpMinor, (gss_cred_id_t)creds,
191*7f2fe78bSCy Schubert desired_name, &mechs->elements[i],
192*7f2fe78bSCy Schubert cred_usage, time_req, time_req,
193*7f2fe78bSCy Schubert cred_store, NULL, NULL,
194*7f2fe78bSCy Schubert time_rec ? &initTimeOut : NULL,
195*7f2fe78bSCy Schubert time_rec ? &acceptTimeOut : NULL);
196*7f2fe78bSCy Schubert if (major == GSS_S_COMPLETE) {
197*7f2fe78bSCy Schubert /* update the credential's time */
198*7f2fe78bSCy Schubert if (cred_usage == GSS_C_ACCEPT) {
199*7f2fe78bSCy Schubert if (outTime > acceptTimeOut)
200*7f2fe78bSCy Schubert outTime = acceptTimeOut;
201*7f2fe78bSCy Schubert } else if (cred_usage == GSS_C_INITIATE) {
202*7f2fe78bSCy Schubert if (outTime > initTimeOut)
203*7f2fe78bSCy Schubert outTime = initTimeOut;
204*7f2fe78bSCy Schubert } else {
205*7f2fe78bSCy Schubert /*
206*7f2fe78bSCy Schubert * time_rec is the lesser of the
207*7f2fe78bSCy Schubert * init/accept times
208*7f2fe78bSCy Schubert */
209*7f2fe78bSCy Schubert if (initTimeOut > acceptTimeOut)
210*7f2fe78bSCy Schubert outTime = (outTime > acceptTimeOut) ?
211*7f2fe78bSCy Schubert acceptTimeOut : outTime;
212*7f2fe78bSCy Schubert else
213*7f2fe78bSCy Schubert outTime = (outTime > initTimeOut) ?
214*7f2fe78bSCy Schubert initTimeOut : outTime;
215*7f2fe78bSCy Schubert }
216*7f2fe78bSCy Schubert } else if (first_major == GSS_S_COMPLETE) {
217*7f2fe78bSCy Schubert first_major = major;
218*7f2fe78bSCy Schubert first_minor = tmpMinor;
219*7f2fe78bSCy Schubert }
220*7f2fe78bSCy Schubert } /* for */
221*7f2fe78bSCy Schubert
222*7f2fe78bSCy Schubert /* If we didn't get any creds, return the error status from the first mech
223*7f2fe78bSCy Schubert * (which is often the preferred one). */
224*7f2fe78bSCy Schubert if (creds->count < 1) {
225*7f2fe78bSCy Schubert major = first_major;
226*7f2fe78bSCy Schubert *minor_status = first_minor;
227*7f2fe78bSCy Schubert goto cleanup;
228*7f2fe78bSCy Schubert }
229*7f2fe78bSCy Schubert major = GSS_S_COMPLETE;
230*7f2fe78bSCy Schubert
231*7f2fe78bSCy Schubert /*
232*7f2fe78bSCy Schubert * fill in output parameters
233*7f2fe78bSCy Schubert * setup the actual mechs output parameter
234*7f2fe78bSCy Schubert */
235*7f2fe78bSCy Schubert if (actual_mechs != NULL) {
236*7f2fe78bSCy Schubert major = gssint_make_public_oid_set(minor_status, creds->mechs_array,
237*7f2fe78bSCy Schubert creds->count, actual_mechs);
238*7f2fe78bSCy Schubert if (GSS_ERROR(major))
239*7f2fe78bSCy Schubert goto cleanup;
240*7f2fe78bSCy Schubert }
241*7f2fe78bSCy Schubert
242*7f2fe78bSCy Schubert if (time_rec)
243*7f2fe78bSCy Schubert *time_rec = outTime;
244*7f2fe78bSCy Schubert
245*7f2fe78bSCy Schubert *output_cred_handle = (gss_cred_id_t)creds;
246*7f2fe78bSCy Schubert
247*7f2fe78bSCy Schubert cleanup:
248*7f2fe78bSCy Schubert if (GSS_ERROR(major))
249*7f2fe78bSCy Schubert gss_release_cred(&tmpMinor, (gss_cred_id_t *)&creds);
250*7f2fe78bSCy Schubert if (desired_mechs == GSS_C_NO_OID_SET)
251*7f2fe78bSCy Schubert generic_gss_release_oid_set(&tmpMinor, &mechs);
252*7f2fe78bSCy Schubert
253*7f2fe78bSCy Schubert return (major);
254*7f2fe78bSCy Schubert }
255*7f2fe78bSCy Schubert
256*7f2fe78bSCy Schubert static OM_uint32
val_add_cred_args(OM_uint32 * minor_status,gss_cred_id_t input_cred_handle,gss_name_t desired_name,gss_OID desired_mech,gss_cred_usage_t cred_usage,gss_const_key_value_set_t cred_store,OM_uint32 initiator_time_req,OM_uint32 acceptor_time_req,gss_cred_id_t * output_cred_handle,gss_OID_set * actual_mechs,OM_uint32 * initiator_time_rec,OM_uint32 * acceptor_time_rec)257*7f2fe78bSCy Schubert val_add_cred_args(
258*7f2fe78bSCy Schubert OM_uint32 *minor_status,
259*7f2fe78bSCy Schubert gss_cred_id_t input_cred_handle,
260*7f2fe78bSCy Schubert gss_name_t desired_name,
261*7f2fe78bSCy Schubert gss_OID desired_mech,
262*7f2fe78bSCy Schubert gss_cred_usage_t cred_usage,
263*7f2fe78bSCy Schubert gss_const_key_value_set_t cred_store,
264*7f2fe78bSCy Schubert OM_uint32 initiator_time_req,
265*7f2fe78bSCy Schubert OM_uint32 acceptor_time_req,
266*7f2fe78bSCy Schubert gss_cred_id_t *output_cred_handle,
267*7f2fe78bSCy Schubert gss_OID_set *actual_mechs,
268*7f2fe78bSCy Schubert OM_uint32 *initiator_time_rec,
269*7f2fe78bSCy Schubert OM_uint32 *acceptor_time_rec)
270*7f2fe78bSCy Schubert {
271*7f2fe78bSCy Schubert
272*7f2fe78bSCy Schubert /* Initialize outputs. */
273*7f2fe78bSCy Schubert
274*7f2fe78bSCy Schubert if (minor_status != NULL)
275*7f2fe78bSCy Schubert *minor_status = 0;
276*7f2fe78bSCy Schubert
277*7f2fe78bSCy Schubert if (output_cred_handle != NULL)
278*7f2fe78bSCy Schubert *output_cred_handle = GSS_C_NO_CREDENTIAL;
279*7f2fe78bSCy Schubert
280*7f2fe78bSCy Schubert if (actual_mechs != NULL)
281*7f2fe78bSCy Schubert *actual_mechs = GSS_C_NO_OID_SET;
282*7f2fe78bSCy Schubert
283*7f2fe78bSCy Schubert if (acceptor_time_rec != NULL)
284*7f2fe78bSCy Schubert *acceptor_time_rec = 0;
285*7f2fe78bSCy Schubert
286*7f2fe78bSCy Schubert if (initiator_time_rec != NULL)
287*7f2fe78bSCy Schubert *initiator_time_rec = 0;
288*7f2fe78bSCy Schubert
289*7f2fe78bSCy Schubert /* Validate arguments. */
290*7f2fe78bSCy Schubert
291*7f2fe78bSCy Schubert if (minor_status == NULL)
292*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_WRITE);
293*7f2fe78bSCy Schubert
294*7f2fe78bSCy Schubert if (input_cred_handle == GSS_C_NO_CREDENTIAL &&
295*7f2fe78bSCy Schubert output_cred_handle == NULL)
296*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
297*7f2fe78bSCy Schubert
298*7f2fe78bSCy Schubert if (cred_usage != GSS_C_ACCEPT
299*7f2fe78bSCy Schubert && cred_usage != GSS_C_INITIATE
300*7f2fe78bSCy Schubert && cred_usage != GSS_C_BOTH) {
301*7f2fe78bSCy Schubert if (minor_status) {
302*7f2fe78bSCy Schubert *minor_status = EINVAL;
303*7f2fe78bSCy Schubert map_errcode(minor_status);
304*7f2fe78bSCy Schubert }
305*7f2fe78bSCy Schubert return GSS_S_FAILURE;
306*7f2fe78bSCy Schubert }
307*7f2fe78bSCy Schubert
308*7f2fe78bSCy Schubert return (GSS_S_COMPLETE);
309*7f2fe78bSCy Schubert }
310*7f2fe78bSCy Schubert
311*7f2fe78bSCy Schubert /* Copy a mechanism credential (with the mechanism given by mech_oid) as
312*7f2fe78bSCy Schubert * faithfully as possible. */
313*7f2fe78bSCy Schubert static OM_uint32
copy_mech_cred(OM_uint32 * minor_status,gss_cred_id_t cred_in,gss_OID mech_oid,gss_cred_id_t * cred_out)314*7f2fe78bSCy Schubert copy_mech_cred(OM_uint32 *minor_status, gss_cred_id_t cred_in,
315*7f2fe78bSCy Schubert gss_OID mech_oid, gss_cred_id_t *cred_out)
316*7f2fe78bSCy Schubert {
317*7f2fe78bSCy Schubert OM_uint32 status, tmpmin;
318*7f2fe78bSCy Schubert gss_mechanism mech;
319*7f2fe78bSCy Schubert gss_buffer_desc buf;
320*7f2fe78bSCy Schubert gss_name_t name;
321*7f2fe78bSCy Schubert OM_uint32 life;
322*7f2fe78bSCy Schubert gss_cred_usage_t usage;
323*7f2fe78bSCy Schubert gss_OID_set_desc oidset;
324*7f2fe78bSCy Schubert
325*7f2fe78bSCy Schubert mech = gssint_get_mechanism(mech_oid);
326*7f2fe78bSCy Schubert if (mech == NULL)
327*7f2fe78bSCy Schubert return (GSS_S_BAD_MECH);
328*7f2fe78bSCy Schubert if (mech->gss_export_cred != NULL && mech->gss_import_cred != NULL) {
329*7f2fe78bSCy Schubert status = mech->gss_export_cred(minor_status, cred_in, &buf);
330*7f2fe78bSCy Schubert if (status != GSS_S_COMPLETE)
331*7f2fe78bSCy Schubert return (status);
332*7f2fe78bSCy Schubert status = mech->gss_import_cred(minor_status, &buf, cred_out);
333*7f2fe78bSCy Schubert (void) gss_release_buffer(&tmpmin, &buf);
334*7f2fe78bSCy Schubert } else if (mech->gss_inquire_cred != NULL &&
335*7f2fe78bSCy Schubert mech->gss_acquire_cred != NULL) {
336*7f2fe78bSCy Schubert status = mech->gss_inquire_cred(minor_status, cred_in, &name, &life,
337*7f2fe78bSCy Schubert &usage, NULL);
338*7f2fe78bSCy Schubert if (status != GSS_S_COMPLETE)
339*7f2fe78bSCy Schubert return (status);
340*7f2fe78bSCy Schubert oidset.count = 1;
341*7f2fe78bSCy Schubert oidset.elements = gssint_get_public_oid(mech_oid);
342*7f2fe78bSCy Schubert status = mech->gss_acquire_cred(minor_status, name, life, &oidset,
343*7f2fe78bSCy Schubert usage, cred_out, NULL, NULL);
344*7f2fe78bSCy Schubert gss_release_name(&tmpmin, &name);
345*7f2fe78bSCy Schubert } else {
346*7f2fe78bSCy Schubert status = GSS_S_UNAVAILABLE;
347*7f2fe78bSCy Schubert }
348*7f2fe78bSCy Schubert return (status);
349*7f2fe78bSCy Schubert }
350*7f2fe78bSCy Schubert
351*7f2fe78bSCy Schubert /* Copy a union credential from cred_in to *cred_out. */
352*7f2fe78bSCy Schubert static OM_uint32
copy_union_cred(OM_uint32 * minor_status,gss_cred_id_t cred_in,gss_union_cred_t * cred_out)353*7f2fe78bSCy Schubert copy_union_cred(OM_uint32 *minor_status, gss_cred_id_t cred_in,
354*7f2fe78bSCy Schubert gss_union_cred_t *cred_out)
355*7f2fe78bSCy Schubert {
356*7f2fe78bSCy Schubert OM_uint32 status, tmpmin;
357*7f2fe78bSCy Schubert gss_union_cred_t cred = (gss_union_cred_t)cred_in;
358*7f2fe78bSCy Schubert gss_union_cred_t ncred = NULL;
359*7f2fe78bSCy Schubert gss_cred_id_t tmpcred;
360*7f2fe78bSCy Schubert int i;
361*7f2fe78bSCy Schubert
362*7f2fe78bSCy Schubert ncred = calloc(1, sizeof (*ncred));
363*7f2fe78bSCy Schubert if (ncred == NULL)
364*7f2fe78bSCy Schubert goto oom;
365*7f2fe78bSCy Schubert ncred->mechs_array = calloc(cred->count, sizeof (*ncred->mechs_array));
366*7f2fe78bSCy Schubert ncred->cred_array = calloc(cred->count, sizeof (*ncred->cred_array));
367*7f2fe78bSCy Schubert if (ncred->mechs_array == NULL || ncred->cred_array == NULL)
368*7f2fe78bSCy Schubert goto oom;
369*7f2fe78bSCy Schubert ncred->count = cred->count;
370*7f2fe78bSCy Schubert
371*7f2fe78bSCy Schubert for (i = 0; i < cred->count; i++) {
372*7f2fe78bSCy Schubert /* Copy this element's mechanism OID. */
373*7f2fe78bSCy Schubert ncred->mechs_array[i].elements = malloc(cred->mechs_array[i].length);
374*7f2fe78bSCy Schubert if (ncred->mechs_array[i].elements == NULL)
375*7f2fe78bSCy Schubert goto oom;
376*7f2fe78bSCy Schubert g_OID_copy(&ncred->mechs_array[i], &cred->mechs_array[i]);
377*7f2fe78bSCy Schubert
378*7f2fe78bSCy Schubert /* Copy this element's mechanism cred. */
379*7f2fe78bSCy Schubert status = copy_mech_cred(minor_status, cred->cred_array[i],
380*7f2fe78bSCy Schubert &cred->mechs_array[i], &ncred->cred_array[i]);
381*7f2fe78bSCy Schubert if (status != GSS_S_COMPLETE)
382*7f2fe78bSCy Schubert goto error;
383*7f2fe78bSCy Schubert }
384*7f2fe78bSCy Schubert
385*7f2fe78bSCy Schubert ncred->loopback = ncred;
386*7f2fe78bSCy Schubert *cred_out = ncred;
387*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
388*7f2fe78bSCy Schubert
389*7f2fe78bSCy Schubert oom:
390*7f2fe78bSCy Schubert status = GSS_S_FAILURE;
391*7f2fe78bSCy Schubert *minor_status = ENOMEM;
392*7f2fe78bSCy Schubert error:
393*7f2fe78bSCy Schubert tmpcred = (gss_cred_id_t)ncred;
394*7f2fe78bSCy Schubert (void) gss_release_cred(&tmpmin, &tmpcred);
395*7f2fe78bSCy Schubert return status;
396*7f2fe78bSCy Schubert }
397*7f2fe78bSCy Schubert
398*7f2fe78bSCy Schubert /* V2 KRB5_CALLCONV */
399*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_add_cred(minor_status,input_cred_handle,desired_name,desired_mech,cred_usage,initiator_time_req,acceptor_time_req,output_cred_handle,actual_mechs,initiator_time_rec,acceptor_time_rec)400*7f2fe78bSCy Schubert gss_add_cred(minor_status, input_cred_handle,
401*7f2fe78bSCy Schubert desired_name, desired_mech, cred_usage,
402*7f2fe78bSCy Schubert initiator_time_req, acceptor_time_req,
403*7f2fe78bSCy Schubert output_cred_handle, actual_mechs,
404*7f2fe78bSCy Schubert initiator_time_rec, acceptor_time_rec)
405*7f2fe78bSCy Schubert OM_uint32 *minor_status;
406*7f2fe78bSCy Schubert gss_cred_id_t input_cred_handle;
407*7f2fe78bSCy Schubert gss_name_t desired_name;
408*7f2fe78bSCy Schubert gss_OID desired_mech;
409*7f2fe78bSCy Schubert gss_cred_usage_t cred_usage;
410*7f2fe78bSCy Schubert OM_uint32 initiator_time_req;
411*7f2fe78bSCy Schubert OM_uint32 acceptor_time_req;
412*7f2fe78bSCy Schubert gss_cred_id_t *output_cred_handle;
413*7f2fe78bSCy Schubert gss_OID_set *actual_mechs;
414*7f2fe78bSCy Schubert OM_uint32 *initiator_time_rec;
415*7f2fe78bSCy Schubert OM_uint32 *acceptor_time_rec;
416*7f2fe78bSCy Schubert {
417*7f2fe78bSCy Schubert return gss_add_cred_from(minor_status, input_cred_handle, desired_name,
418*7f2fe78bSCy Schubert desired_mech, cred_usage, initiator_time_req,
419*7f2fe78bSCy Schubert acceptor_time_req, NULL, output_cred_handle,
420*7f2fe78bSCy Schubert actual_mechs, initiator_time_rec,
421*7f2fe78bSCy Schubert acceptor_time_rec);
422*7f2fe78bSCy Schubert }
423*7f2fe78bSCy Schubert
424*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_add_cred_from(minor_status,input_cred_handle,desired_name,desired_mech,cred_usage,initiator_time_req,acceptor_time_req,cred_store,output_cred_handle,actual_mechs,initiator_time_rec,acceptor_time_rec)425*7f2fe78bSCy Schubert gss_add_cred_from(minor_status, input_cred_handle,
426*7f2fe78bSCy Schubert desired_name, desired_mech,
427*7f2fe78bSCy Schubert cred_usage,
428*7f2fe78bSCy Schubert initiator_time_req, acceptor_time_req,
429*7f2fe78bSCy Schubert cred_store,
430*7f2fe78bSCy Schubert output_cred_handle, actual_mechs,
431*7f2fe78bSCy Schubert initiator_time_rec, acceptor_time_rec)
432*7f2fe78bSCy Schubert OM_uint32 *minor_status;
433*7f2fe78bSCy Schubert gss_cred_id_t input_cred_handle;
434*7f2fe78bSCy Schubert gss_name_t desired_name;
435*7f2fe78bSCy Schubert gss_OID desired_mech;
436*7f2fe78bSCy Schubert gss_cred_usage_t cred_usage;
437*7f2fe78bSCy Schubert OM_uint32 initiator_time_req;
438*7f2fe78bSCy Schubert OM_uint32 acceptor_time_req;
439*7f2fe78bSCy Schubert gss_const_key_value_set_t cred_store;
440*7f2fe78bSCy Schubert gss_cred_id_t *output_cred_handle;
441*7f2fe78bSCy Schubert gss_OID_set *actual_mechs;
442*7f2fe78bSCy Schubert OM_uint32 *initiator_time_rec;
443*7f2fe78bSCy Schubert OM_uint32 *acceptor_time_rec;
444*7f2fe78bSCy Schubert {
445*7f2fe78bSCy Schubert OM_uint32 status, temp_minor_status;
446*7f2fe78bSCy Schubert OM_uint32 time_req, time_rec = 0, *time_recp = NULL;
447*7f2fe78bSCy Schubert gss_union_name_t union_name;
448*7f2fe78bSCy Schubert gss_union_cred_t union_cred;
449*7f2fe78bSCy Schubert gss_name_t internal_name = GSS_C_NO_NAME;
450*7f2fe78bSCy Schubert gss_name_t allocated_name = GSS_C_NO_NAME;
451*7f2fe78bSCy Schubert gss_mechanism mech;
452*7f2fe78bSCy Schubert gss_cred_id_t cred = NULL, tmpcred;
453*7f2fe78bSCy Schubert void *newptr, *oidbuf = NULL;
454*7f2fe78bSCy Schubert gss_OID_set_desc target_mechs;
455*7f2fe78bSCy Schubert gss_OID selected_mech = GSS_C_NO_OID;
456*7f2fe78bSCy Schubert
457*7f2fe78bSCy Schubert status = val_add_cred_args(minor_status,
458*7f2fe78bSCy Schubert input_cred_handle,
459*7f2fe78bSCy Schubert desired_name,
460*7f2fe78bSCy Schubert desired_mech,
461*7f2fe78bSCy Schubert cred_usage,
462*7f2fe78bSCy Schubert cred_store,
463*7f2fe78bSCy Schubert initiator_time_req,
464*7f2fe78bSCy Schubert acceptor_time_req,
465*7f2fe78bSCy Schubert output_cred_handle,
466*7f2fe78bSCy Schubert actual_mechs,
467*7f2fe78bSCy Schubert initiator_time_rec,
468*7f2fe78bSCy Schubert acceptor_time_rec);
469*7f2fe78bSCy Schubert if (status != GSS_S_COMPLETE)
470*7f2fe78bSCy Schubert return (status);
471*7f2fe78bSCy Schubert
472*7f2fe78bSCy Schubert status = gssint_select_mech_type(minor_status, desired_mech,
473*7f2fe78bSCy Schubert &selected_mech);
474*7f2fe78bSCy Schubert if (status != GSS_S_COMPLETE)
475*7f2fe78bSCy Schubert return (status);
476*7f2fe78bSCy Schubert
477*7f2fe78bSCy Schubert mech = gssint_get_mechanism(selected_mech);
478*7f2fe78bSCy Schubert if (!mech)
479*7f2fe78bSCy Schubert return GSS_S_BAD_MECH;
480*7f2fe78bSCy Schubert else if (!mech->gss_acquire_cred)
481*7f2fe78bSCy Schubert return (GSS_S_UNAVAILABLE);
482*7f2fe78bSCy Schubert
483*7f2fe78bSCy Schubert union_cred = (gss_union_cred_t)input_cred_handle;
484*7f2fe78bSCy Schubert if (union_cred != NULL &&
485*7f2fe78bSCy Schubert gssint_get_mechanism_cred(union_cred,
486*7f2fe78bSCy Schubert selected_mech) != GSS_C_NO_CREDENTIAL)
487*7f2fe78bSCy Schubert return (GSS_S_DUPLICATE_ELEMENT);
488*7f2fe78bSCy Schubert
489*7f2fe78bSCy Schubert if (union_cred == NULL) {
490*7f2fe78bSCy Schubert /* Create a new credential handle. */
491*7f2fe78bSCy Schubert union_cred = malloc(sizeof (gss_union_cred_desc));
492*7f2fe78bSCy Schubert if (union_cred == NULL)
493*7f2fe78bSCy Schubert return (GSS_S_FAILURE);
494*7f2fe78bSCy Schubert
495*7f2fe78bSCy Schubert (void) memset(union_cred, 0, sizeof (gss_union_cred_desc));
496*7f2fe78bSCy Schubert union_cred->loopback = union_cred;
497*7f2fe78bSCy Schubert } else if (output_cred_handle != NULL) {
498*7f2fe78bSCy Schubert /* Create a new credential handle with the mechanism credentials of the
499*7f2fe78bSCy Schubert * input handle plus the acquired mechanism credential. */
500*7f2fe78bSCy Schubert status = copy_union_cred(minor_status, input_cred_handle, &union_cred);
501*7f2fe78bSCy Schubert if (status != GSS_S_COMPLETE)
502*7f2fe78bSCy Schubert return (status);
503*7f2fe78bSCy Schubert }
504*7f2fe78bSCy Schubert
505*7f2fe78bSCy Schubert /* We may need to create a mechanism specific name. */
506*7f2fe78bSCy Schubert if (desired_name != GSS_C_NO_NAME) {
507*7f2fe78bSCy Schubert union_name = (gss_union_name_t)desired_name;
508*7f2fe78bSCy Schubert if (union_name->mech_type &&
509*7f2fe78bSCy Schubert g_OID_equal(union_name->mech_type, selected_mech)) {
510*7f2fe78bSCy Schubert internal_name = union_name->mech_name;
511*7f2fe78bSCy Schubert } else {
512*7f2fe78bSCy Schubert if (gssint_import_internal_name(minor_status, selected_mech,
513*7f2fe78bSCy Schubert union_name, &allocated_name) !=
514*7f2fe78bSCy Schubert GSS_S_COMPLETE) {
515*7f2fe78bSCy Schubert status = GSS_S_BAD_NAME;
516*7f2fe78bSCy Schubert goto errout;
517*7f2fe78bSCy Schubert }
518*7f2fe78bSCy Schubert internal_name = allocated_name;
519*7f2fe78bSCy Schubert }
520*7f2fe78bSCy Schubert }
521*7f2fe78bSCy Schubert
522*7f2fe78bSCy Schubert
523*7f2fe78bSCy Schubert if (cred_usage == GSS_C_ACCEPT)
524*7f2fe78bSCy Schubert time_req = acceptor_time_req;
525*7f2fe78bSCy Schubert else if (cred_usage == GSS_C_INITIATE)
526*7f2fe78bSCy Schubert time_req = initiator_time_req;
527*7f2fe78bSCy Schubert else if (cred_usage == GSS_C_BOTH)
528*7f2fe78bSCy Schubert time_req = (acceptor_time_req > initiator_time_req) ?
529*7f2fe78bSCy Schubert acceptor_time_req : initiator_time_req;
530*7f2fe78bSCy Schubert else
531*7f2fe78bSCy Schubert time_req = 0;
532*7f2fe78bSCy Schubert
533*7f2fe78bSCy Schubert target_mechs.count = 1;
534*7f2fe78bSCy Schubert target_mechs.elements = gssint_get_public_oid(selected_mech);
535*7f2fe78bSCy Schubert if (target_mechs.elements == NULL) {
536*7f2fe78bSCy Schubert status = GSS_S_FAILURE;
537*7f2fe78bSCy Schubert goto errout;
538*7f2fe78bSCy Schubert }
539*7f2fe78bSCy Schubert
540*7f2fe78bSCy Schubert if (initiator_time_rec != NULL || acceptor_time_rec != NULL)
541*7f2fe78bSCy Schubert time_recp = &time_rec;
542*7f2fe78bSCy Schubert
543*7f2fe78bSCy Schubert if (mech->gss_acquire_cred_from) {
544*7f2fe78bSCy Schubert status = mech->gss_acquire_cred_from(minor_status, internal_name,
545*7f2fe78bSCy Schubert time_req, &target_mechs,
546*7f2fe78bSCy Schubert cred_usage, cred_store, &cred,
547*7f2fe78bSCy Schubert NULL, time_recp);
548*7f2fe78bSCy Schubert } else if (cred_store == GSS_C_NO_CRED_STORE) {
549*7f2fe78bSCy Schubert status = mech->gss_acquire_cred(minor_status, internal_name, time_req,
550*7f2fe78bSCy Schubert &target_mechs, cred_usage, &cred, NULL,
551*7f2fe78bSCy Schubert time_recp);
552*7f2fe78bSCy Schubert } else {
553*7f2fe78bSCy Schubert status = GSS_S_UNAVAILABLE;
554*7f2fe78bSCy Schubert goto errout;
555*7f2fe78bSCy Schubert }
556*7f2fe78bSCy Schubert
557*7f2fe78bSCy Schubert if (status != GSS_S_COMPLETE) {
558*7f2fe78bSCy Schubert map_error(minor_status, mech);
559*7f2fe78bSCy Schubert goto errout;
560*7f2fe78bSCy Schubert }
561*7f2fe78bSCy Schubert
562*7f2fe78bSCy Schubert /* Extend the arrays in the union cred. */
563*7f2fe78bSCy Schubert
564*7f2fe78bSCy Schubert newptr = realloc(union_cred->mechs_array,
565*7f2fe78bSCy Schubert (union_cred->count + 1) * sizeof (gss_OID_desc));
566*7f2fe78bSCy Schubert if (newptr == NULL) {
567*7f2fe78bSCy Schubert status = GSS_S_FAILURE;
568*7f2fe78bSCy Schubert goto errout;
569*7f2fe78bSCy Schubert }
570*7f2fe78bSCy Schubert union_cred->mechs_array = newptr;
571*7f2fe78bSCy Schubert
572*7f2fe78bSCy Schubert newptr = realloc(union_cred->cred_array,
573*7f2fe78bSCy Schubert (union_cred->count + 1) * sizeof (gss_cred_id_t));
574*7f2fe78bSCy Schubert if (newptr == NULL) {
575*7f2fe78bSCy Schubert status = GSS_S_FAILURE;
576*7f2fe78bSCy Schubert goto errout;
577*7f2fe78bSCy Schubert }
578*7f2fe78bSCy Schubert union_cred->cred_array = newptr;
579*7f2fe78bSCy Schubert
580*7f2fe78bSCy Schubert if (acceptor_time_rec)
581*7f2fe78bSCy Schubert if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH)
582*7f2fe78bSCy Schubert *acceptor_time_rec = time_rec;
583*7f2fe78bSCy Schubert if (initiator_time_rec)
584*7f2fe78bSCy Schubert if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH)
585*7f2fe78bSCy Schubert *initiator_time_rec = time_rec;
586*7f2fe78bSCy Schubert
587*7f2fe78bSCy Schubert oidbuf = malloc(selected_mech->length);
588*7f2fe78bSCy Schubert if (oidbuf == NULL)
589*7f2fe78bSCy Schubert goto errout;
590*7f2fe78bSCy Schubert union_cred->mechs_array[union_cred->count].elements = oidbuf;
591*7f2fe78bSCy Schubert g_OID_copy(&union_cred->mechs_array[union_cred->count], selected_mech);
592*7f2fe78bSCy Schubert
593*7f2fe78bSCy Schubert if (actual_mechs != NULL) {
594*7f2fe78bSCy Schubert status = gssint_make_public_oid_set(minor_status,
595*7f2fe78bSCy Schubert union_cred->mechs_array,
596*7f2fe78bSCy Schubert union_cred->count + 1,
597*7f2fe78bSCy Schubert actual_mechs);
598*7f2fe78bSCy Schubert if (GSS_ERROR(status))
599*7f2fe78bSCy Schubert goto errout;
600*7f2fe78bSCy Schubert }
601*7f2fe78bSCy Schubert
602*7f2fe78bSCy Schubert union_cred->cred_array[union_cred->count] = cred;
603*7f2fe78bSCy Schubert union_cred->count++;
604*7f2fe78bSCy Schubert if (output_cred_handle != NULL)
605*7f2fe78bSCy Schubert *output_cred_handle = (gss_cred_id_t)union_cred;
606*7f2fe78bSCy Schubert
607*7f2fe78bSCy Schubert /* We're done with the internal name. Free it if we allocated it. */
608*7f2fe78bSCy Schubert
609*7f2fe78bSCy Schubert if (allocated_name)
610*7f2fe78bSCy Schubert (void) gssint_release_internal_name(&temp_minor_status,
611*7f2fe78bSCy Schubert selected_mech,
612*7f2fe78bSCy Schubert &allocated_name);
613*7f2fe78bSCy Schubert
614*7f2fe78bSCy Schubert return (GSS_S_COMPLETE);
615*7f2fe78bSCy Schubert
616*7f2fe78bSCy Schubert errout:
617*7f2fe78bSCy Schubert if (cred != NULL && mech->gss_release_cred)
618*7f2fe78bSCy Schubert mech->gss_release_cred(&temp_minor_status, &cred);
619*7f2fe78bSCy Schubert
620*7f2fe78bSCy Schubert if (allocated_name)
621*7f2fe78bSCy Schubert (void) gssint_release_internal_name(&temp_minor_status,
622*7f2fe78bSCy Schubert selected_mech,
623*7f2fe78bSCy Schubert &allocated_name);
624*7f2fe78bSCy Schubert
625*7f2fe78bSCy Schubert if (output_cred_handle != NULL && union_cred != NULL) {
626*7f2fe78bSCy Schubert tmpcred = union_cred;
627*7f2fe78bSCy Schubert (void) gss_release_cred(&temp_minor_status, &tmpcred);
628*7f2fe78bSCy Schubert }
629*7f2fe78bSCy Schubert
630*7f2fe78bSCy Schubert free(oidbuf);
631*7f2fe78bSCy Schubert
632*7f2fe78bSCy Schubert return (status);
633*7f2fe78bSCy Schubert }
634