remove pyzfs
[unleashed.git] / usr / src / lib / libgss / g_acquire_cred_with_pw.c
blobe5a39f93a78a3d2afe43a15197494f8f3be1822a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * glue routine for gss_acquire_cred
31 #include <mechglueP.h>
32 #include <gssapi/gssapi_ext.h>
33 #include <stdio.h>
34 #ifdef HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37 #include <string.h>
38 #include <errno.h>
39 #include <time.h>
40 /* local functions */
41 static gss_OID_set create_actual_mechs(const gss_OID, int);
43 static gss_OID_set
44 create_actual_mechs(mechs_array, count)
45 const gss_OID mechs_array;
46 int count;
48 gss_OID_set actual_mechs;
49 int i;
50 OM_uint32 minor;
52 actual_mechs = (gss_OID_set) malloc(sizeof (gss_OID_set_desc));
53 if (!actual_mechs)
54 return (NULL);
56 actual_mechs->elements = (gss_OID)
57 malloc(sizeof (gss_OID_desc) * count);
58 if (!actual_mechs->elements) {
59 free(actual_mechs);
60 return (NULL);
63 actual_mechs->count = 0;
65 for (i = 0; i < count; i++) {
66 actual_mechs->elements[i].elements = (void *)
67 malloc(mechs_array[i].length);
68 if (actual_mechs->elements[i].elements == NULL) {
69 (void) gss_release_oid_set(&minor, &actual_mechs);
70 return (NULL);
72 g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]);
73 actual_mechs->count++;
76 return (actual_mechs);
80 OM_uint32
81 gss_acquire_cred_with_password(minor_status,
82 desired_name,
83 password,
84 time_req,
85 desired_mechs,
86 cred_usage,
87 output_cred_handle,
88 actual_mechs,
89 time_rec)
91 OM_uint32 * minor_status;
92 const gss_name_t desired_name;
93 const gss_buffer_t password;
94 OM_uint32 time_req;
95 const gss_OID_set desired_mechs;
96 int cred_usage;
97 gss_cred_id_t *output_cred_handle;
98 gss_OID_set * actual_mechs;
99 OM_uint32 * time_rec;
102 OM_uint32 major = GSS_S_FAILURE;
103 OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE;
104 gss_OID_set_desc default_OID_set;
105 gss_OID_set mechs;
106 gss_OID_desc default_OID;
107 gss_mechanism mech;
108 int i;
109 gss_union_cred_t creds;
111 /* start by checking parameters */
112 if (minor_status == NULL)
113 return (GSS_S_CALL_INACCESSIBLE_WRITE);
114 *minor_status = 0;
116 if (desired_name == GSS_C_NO_NAME)
117 return (GSS_S_BAD_NAME);
119 if (output_cred_handle == NULL)
120 return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
122 *output_cred_handle = GSS_C_NO_CREDENTIAL;
124 /* Set output parameters to NULL for now */
125 if (actual_mechs != NULL)
126 *actual_mechs = GSS_C_NULL_OID_SET;
128 if (time_rec)
129 *time_rec = 0;
132 * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an
133 * appropriate default. We use the first mechanism in the
134 * mechansim list as the default. This set is created with
135 * statics thus needs not be freed
137 if (desired_mechs == GSS_C_NULL_OID_SET) {
138 mech = __gss_get_mechanism(GSS_C_NULL_OID);
139 if (mech == NULL)
140 return (GSS_S_BAD_MECH);
142 mechs = &default_OID_set;
143 default_OID_set.count = 1;
144 default_OID_set.elements = &default_OID;
145 default_OID.length = mech->mech_type.length;
146 default_OID.elements = mech->mech_type.elements;
147 } else
148 mechs = desired_mechs;
150 if (mechs->count == 0)
151 return (GSS_S_BAD_MECH);
153 /* allocate the output credential structure */
154 creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc));
155 if (creds == NULL)
156 return (GSS_S_FAILURE);
158 /* initialize to 0s */
159 (void) memset(creds, 0, sizeof (gss_union_cred_desc));
161 /* for each requested mech attempt to obtain a credential */
162 for (i = 0; i < mechs->count; i++) {
163 major = gss_add_cred_with_password(minor_status,
164 (gss_cred_id_t)creds,
165 desired_name,
166 &mechs->elements[i],
167 password,
168 cred_usage, time_req, time_req, NULL,
169 NULL, &initTimeOut, &acceptTimeOut);
170 if (major == GSS_S_COMPLETE) {
171 /* update the credential's time */
172 if (cred_usage == GSS_C_ACCEPT) {
173 if (outTime > acceptTimeOut)
174 outTime = acceptTimeOut;
175 } else if (cred_usage == GSS_C_INITIATE) {
176 if (outTime > initTimeOut)
177 outTime = initTimeOut;
178 } else {
180 * time_rec is the lesser of the
181 * init/accept times
183 if (initTimeOut > acceptTimeOut)
184 outTime = (outTime > acceptTimeOut) ?
185 acceptTimeOut : outTime;
186 else
187 outTime = (outTime > initTimeOut) ?
188 initTimeOut : outTime;
191 } /* for */
193 /* ensure that we have at least one credential element */
194 if (creds->count < 1) {
195 free(creds);
196 return (major);
200 * fill in output parameters
201 * setup the actual mechs output parameter
203 if (actual_mechs != NULL) {
204 if ((*actual_mechs = create_actual_mechs(creds->mechs_array,
205 creds->count)) == NULL) {
206 (void) gss_release_cred(minor_status,
207 (gss_cred_id_t *)&creds);
208 *minor_status = 0;
209 return (GSS_S_FAILURE);
213 if (time_rec)
214 *time_rec = outTime;
217 *output_cred_handle = (gss_cred_id_t)creds;
218 return (GSS_S_COMPLETE);
221 /* V2 INTERFACE */
222 OM_uint32
223 gss_add_cred_with_password(minor_status, input_cred_handle,
224 desired_name, desired_mech, password,
225 cred_usage, initiator_time_req,
226 acceptor_time_req, output_cred_handle,
227 actual_mechs, initiator_time_rec,
228 acceptor_time_rec)
229 OM_uint32 *minor_status;
230 const gss_cred_id_t input_cred_handle;
231 const gss_name_t desired_name;
232 const gss_OID desired_mech;
233 const gss_buffer_t password;
234 gss_cred_usage_t cred_usage;
235 OM_uint32 initiator_time_req;
236 OM_uint32 acceptor_time_req;
237 gss_cred_id_t *output_cred_handle;
238 gss_OID_set *actual_mechs;
239 OM_uint32 *initiator_time_rec;
240 OM_uint32 *acceptor_time_rec;
242 OM_uint32 status, time_req, time_rec, temp_minor_status;
243 gss_mechanism mech;
244 gss_mechanism_ext mech_ext;
245 gss_union_name_t union_name = NULL;
246 gss_union_cred_t union_cred, new_union_cred;
247 gss_name_t internal_name = GSS_C_NO_NAME;
248 gss_name_t allocated_name = GSS_C_NO_NAME;
249 gss_cred_id_t cred = NULL;
250 gss_OID new_mechs_array = NULL;
251 gss_cred_id_t *new_cred_array = NULL;
253 /* check input parameters */
254 if (minor_status == NULL)
255 return (GSS_S_CALL_INACCESSIBLE_WRITE);
256 *minor_status = 0;
258 if (input_cred_handle == GSS_C_NO_CREDENTIAL &&
259 output_cred_handle == NULL)
260 return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
262 if (desired_name == GSS_C_NO_NAME)
263 return (GSS_S_BAD_NAME);
264 union_name = (gss_union_name_t)desired_name;
266 if (output_cred_handle != NULL)
267 *output_cred_handle = GSS_C_NO_CREDENTIAL;
269 if (actual_mechs != NULL)
270 *actual_mechs = NULL;
272 if (acceptor_time_rec != NULL)
273 *acceptor_time_rec = 0;
275 if (initiator_time_rec != NULL)
276 *initiator_time_rec = 0;
278 if ((mech = __gss_get_mechanism(desired_mech)) == NULL)
279 return (GSS_S_BAD_MECH);
281 if ((mech_ext = __gss_get_mechanism_ext(desired_mech)) == NULL ||
282 mech_ext->gss_acquire_cred_with_password == NULL)
283 return (GSS_S_UNAVAILABLE);
285 if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
286 union_cred = malloc(sizeof (gss_union_cred_desc));
287 if (union_cred == NULL)
288 return (GSS_S_FAILURE);
290 (void) memset(union_cred, 0, sizeof (gss_union_cred_desc));
292 } else {
293 union_cred = (gss_union_cred_t)input_cred_handle;
294 if (__gss_get_mechanism_cred(union_cred, desired_mech) !=
295 GSS_C_NO_CREDENTIAL)
296 return (GSS_S_DUPLICATE_ELEMENT);
299 /* May need to create an MN */
300 if (union_name->mech_type &&
301 g_OID_equal(union_name->mech_type,
302 &mech->mech_type))
303 internal_name = union_name->mech_name;
304 else {
305 if (__gss_import_internal_name(minor_status,
306 &mech->mech_type, union_name,
307 &allocated_name) != GSS_S_COMPLETE)
308 return (GSS_S_BAD_NAME);
309 internal_name = allocated_name;
312 if (cred_usage == GSS_C_ACCEPT)
313 time_req = acceptor_time_req;
314 else if (cred_usage == GSS_C_INITIATE)
315 time_req = initiator_time_req;
316 else if (cred_usage == GSS_C_BOTH)
317 time_req = (acceptor_time_req > initiator_time_req) ?
318 acceptor_time_req : initiator_time_req;
320 status = mech_ext->gss_acquire_cred_with_password(mech->context,
321 minor_status, internal_name, password, time_req,
322 GSS_C_NULL_OID_SET, cred_usage, &cred, NULL,
323 &time_rec);
325 if (status != GSS_S_COMPLETE)
326 goto errout;
328 /* May need to set credential auxinfo strucutre */
329 if (union_cred->auxinfo.creation_time == 0) {
330 union_cred->auxinfo.creation_time = time(NULL);
331 union_cred->auxinfo.time_rec = time_rec;
332 union_cred->auxinfo.cred_usage = cred_usage;
334 if ((status = mech->gss_display_name(mech->context,
335 &temp_minor_status, internal_name,
336 &union_cred->auxinfo.name,
337 &union_cred->auxinfo.name_type)) !=
338 GSS_S_COMPLETE)
339 goto errout;
342 /* Now add the new credential elements */
343 new_mechs_array = (gss_OID)
344 malloc(sizeof (gss_OID_desc) * (union_cred->count+1));
346 new_cred_array = (gss_cred_id_t *)
347 malloc(sizeof (gss_cred_id_t) * (union_cred->count+1));
349 if (!new_mechs_array || !new_cred_array) {
350 status = GSS_S_FAILURE;
351 goto errout;
354 if (acceptor_time_rec)
355 if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH)
356 *acceptor_time_rec = time_rec;
357 if (initiator_time_rec)
358 if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH)
359 *initiator_time_rec = time_rec;
362 * OK, expand the mechanism array and the credential array
364 (void) memcpy(new_mechs_array, union_cred->mechs_array,
365 sizeof (gss_OID_desc) * union_cred->count);
366 (void) memcpy(new_cred_array, union_cred->cred_array,
367 sizeof (gss_cred_id_t) * union_cred->count);
369 new_cred_array[union_cred->count] = cred;
370 if ((new_mechs_array[union_cred->count].elements =
371 malloc(mech->mech_type.length)) == NULL)
372 goto errout;
374 g_OID_copy(&new_mechs_array[union_cred->count],
375 &mech->mech_type);
377 if (actual_mechs) {
378 *actual_mechs = create_actual_mechs(new_mechs_array,
379 union_cred->count + 1);
380 if (*actual_mechs == NULL) {
381 free(new_mechs_array[union_cred->count].elements);
382 goto errout;
386 if (output_cred_handle == NULL) {
387 free(union_cred->mechs_array);
388 free(union_cred->cred_array);
389 new_union_cred = union_cred;
390 } else {
391 new_union_cred = malloc(sizeof (gss_union_cred_desc));
392 if (new_union_cred == NULL) {
393 free(new_mechs_array[union_cred->count].elements);
394 goto errout;
396 *new_union_cred = *union_cred;
397 *output_cred_handle = (gss_cred_id_t)new_union_cred;
400 new_union_cred->mechs_array = new_mechs_array;
401 new_union_cred->cred_array = new_cred_array;
402 new_union_cred->count++;
404 /* We're done with the internal name. Free it if we allocated it. */
406 if (allocated_name)
407 (void) __gss_release_internal_name(&temp_minor_status,
408 &mech->mech_type,
409 &allocated_name);
411 return (GSS_S_COMPLETE);
413 errout:
414 free(new_mechs_array);
415 free(new_cred_array);
417 if (cred != NULL && mech->gss_release_cred)
418 mech->gss_release_cred(mech->context,
419 &temp_minor_status, &cred);
421 if (allocated_name)
422 (void) __gss_release_internal_name(&temp_minor_status,
423 &mech->mech_type,
424 &allocated_name);
426 if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) {
427 free(union_cred->auxinfo.name.value);
428 free(union_cred);
431 return (status);