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
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]
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>
41 static gss_OID_set
create_actual_mechs(const gss_OID
, int);
44 create_actual_mechs(mechs_array
, count
)
45 const gss_OID mechs_array
;
48 gss_OID_set actual_mechs
;
52 actual_mechs
= (gss_OID_set
) malloc(sizeof (gss_OID_set_desc
));
56 actual_mechs
->elements
= (gss_OID
)
57 malloc(sizeof (gss_OID_desc
) * count
);
58 if (!actual_mechs
->elements
) {
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
);
72 g_OID_copy(&actual_mechs
->elements
[i
], &mechs_array
[i
]);
73 actual_mechs
->count
++;
76 return (actual_mechs
);
81 gss_acquire_cred_with_password(minor_status
,
91 OM_uint32
* minor_status
;
92 const gss_name_t desired_name
;
93 const gss_buffer_t password
;
95 const gss_OID_set desired_mechs
;
97 gss_cred_id_t
*output_cred_handle
;
98 gss_OID_set
* actual_mechs
;
102 OM_uint32 major
= GSS_S_FAILURE
;
103 OM_uint32 initTimeOut
, acceptTimeOut
, outTime
= GSS_C_INDEFINITE
;
104 gss_OID_set_desc default_OID_set
;
106 gss_OID_desc default_OID
;
109 gss_union_cred_t creds
;
111 /* start by checking parameters */
112 if (minor_status
== NULL
)
113 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
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
;
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
);
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
;
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
));
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
,
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
;
180 * time_rec is the lesser of the
183 if (initTimeOut
> acceptTimeOut
)
184 outTime
= (outTime
> acceptTimeOut
) ?
185 acceptTimeOut
: outTime
;
187 outTime
= (outTime
> initTimeOut
) ?
188 initTimeOut
: outTime
;
193 /* ensure that we have at least one credential element */
194 if (creds
->count
< 1) {
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
);
209 return (GSS_S_FAILURE
);
217 *output_cred_handle
= (gss_cred_id_t
)creds
;
218 return (GSS_S_COMPLETE
);
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
,
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
;
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
);
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
));
293 union_cred
= (gss_union_cred_t
)input_cred_handle
;
294 if (__gss_get_mechanism_cred(union_cred
, desired_mech
) !=
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
,
303 internal_name
= union_name
->mech_name
;
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
,
325 if (status
!= GSS_S_COMPLETE
)
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
)) !=
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
;
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
)
374 g_OID_copy(&new_mechs_array
[union_cred
->count
],
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
);
386 if (output_cred_handle
== NULL
) {
387 free(union_cred
->mechs_array
);
388 free(union_cred
->cred_array
);
389 new_union_cred
= union_cred
;
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
);
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. */
407 (void) __gss_release_internal_name(&temp_minor_status
,
411 return (GSS_S_COMPLETE
);
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
);
422 (void) __gss_release_internal_name(&temp_minor_status
,
426 if (input_cred_handle
== GSS_C_NO_CREDENTIAL
&& union_cred
) {
427 free(union_cred
->auxinfo
.name
.value
);