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.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * glue routine for gss_acquire_cred
33 #include <mechglueP.h>
34 #include <gssapi/gssapi_ext.h>
43 static gss_OID_set
create_actual_mechs(const gss_OID
, int);
46 create_actual_mechs(mechs_array
, count
)
47 const gss_OID mechs_array
;
50 gss_OID_set actual_mechs
;
54 actual_mechs
= (gss_OID_set
) malloc(sizeof (gss_OID_set_desc
));
58 actual_mechs
->elements
= (gss_OID
)
59 malloc(sizeof (gss_OID_desc
) * count
);
60 if (!actual_mechs
->elements
) {
65 actual_mechs
->count
= 0;
67 for (i
= 0; i
< count
; i
++) {
68 actual_mechs
->elements
[i
].elements
= (void *)
69 malloc(mechs_array
[i
].length
);
70 if (actual_mechs
->elements
[i
].elements
== NULL
) {
71 (void) gss_release_oid_set(&minor
, &actual_mechs
);
74 g_OID_copy(&actual_mechs
->elements
[i
], &mechs_array
[i
]);
75 actual_mechs
->count
++;
78 return (actual_mechs
);
83 gss_acquire_cred_with_password(minor_status
,
93 OM_uint32
* minor_status
;
94 const gss_name_t desired_name
;
95 const gss_buffer_t password
;
97 const gss_OID_set desired_mechs
;
99 gss_cred_id_t
*output_cred_handle
;
100 gss_OID_set
* actual_mechs
;
101 OM_uint32
* time_rec
;
104 OM_uint32 major
= GSS_S_FAILURE
;
105 OM_uint32 initTimeOut
, acceptTimeOut
, outTime
= GSS_C_INDEFINITE
;
106 gss_OID_set_desc default_OID_set
;
108 gss_OID_desc default_OID
;
111 gss_union_cred_t creds
;
113 /* start by checking parameters */
114 if (minor_status
== NULL
)
115 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
118 if (desired_name
== GSS_C_NO_NAME
)
119 return (GSS_S_BAD_NAME
);
121 if (output_cred_handle
== NULL
)
122 return (GSS_S_CALL_INACCESSIBLE_WRITE
| GSS_S_NO_CRED
);
124 *output_cred_handle
= GSS_C_NO_CREDENTIAL
;
126 /* Set output parameters to NULL for now */
127 if (actual_mechs
!= NULL
)
128 *actual_mechs
= GSS_C_NULL_OID_SET
;
134 * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an
135 * appropriate default. We use the first mechanism in the
136 * mechansim list as the default. This set is created with
137 * statics thus needs not be freed
139 if (desired_mechs
== GSS_C_NULL_OID_SET
) {
140 mech
= __gss_get_mechanism(GSS_C_NULL_OID
);
142 return (GSS_S_BAD_MECH
);
144 mechs
= &default_OID_set
;
145 default_OID_set
.count
= 1;
146 default_OID_set
.elements
= &default_OID
;
147 default_OID
.length
= mech
->mech_type
.length
;
148 default_OID
.elements
= mech
->mech_type
.elements
;
150 mechs
= desired_mechs
;
152 if (mechs
->count
== 0)
153 return (GSS_S_BAD_MECH
);
155 /* allocate the output credential structure */
156 creds
= (gss_union_cred_t
)malloc(sizeof (gss_union_cred_desc
));
158 return (GSS_S_FAILURE
);
160 /* initialize to 0s */
161 (void) memset(creds
, 0, sizeof (gss_union_cred_desc
));
163 /* for each requested mech attempt to obtain a credential */
164 for (i
= 0; i
< mechs
->count
; i
++) {
165 major
= gss_add_cred_with_password(minor_status
,
166 (gss_cred_id_t
)creds
,
170 cred_usage
, time_req
, time_req
, NULL
,
171 NULL
, &initTimeOut
, &acceptTimeOut
);
172 if (major
== GSS_S_COMPLETE
) {
173 /* update the credential's time */
174 if (cred_usage
== GSS_C_ACCEPT
) {
175 if (outTime
> acceptTimeOut
)
176 outTime
= acceptTimeOut
;
177 } else if (cred_usage
== GSS_C_INITIATE
) {
178 if (outTime
> initTimeOut
)
179 outTime
= initTimeOut
;
182 * time_rec is the lesser of the
185 if (initTimeOut
> acceptTimeOut
)
186 outTime
= (outTime
> acceptTimeOut
) ?
187 acceptTimeOut
: outTime
;
189 outTime
= (outTime
> initTimeOut
) ?
190 initTimeOut
: outTime
;
195 /* ensure that we have at least one credential element */
196 if (creds
->count
< 1) {
202 * fill in output parameters
203 * setup the actual mechs output parameter
205 if (actual_mechs
!= NULL
) {
206 if ((*actual_mechs
= create_actual_mechs(creds
->mechs_array
,
207 creds
->count
)) == NULL
) {
208 (void) gss_release_cred(minor_status
,
209 (gss_cred_id_t
*)&creds
);
211 return (GSS_S_FAILURE
);
219 *output_cred_handle
= (gss_cred_id_t
)creds
;
220 return (GSS_S_COMPLETE
);
225 gss_add_cred_with_password(minor_status
, input_cred_handle
,
226 desired_name
, desired_mech
, password
,
227 cred_usage
, initiator_time_req
,
228 acceptor_time_req
, output_cred_handle
,
229 actual_mechs
, initiator_time_rec
,
231 OM_uint32
*minor_status
;
232 const gss_cred_id_t input_cred_handle
;
233 const gss_name_t desired_name
;
234 const gss_OID desired_mech
;
235 const gss_buffer_t password
;
236 gss_cred_usage_t cred_usage
;
237 OM_uint32 initiator_time_req
;
238 OM_uint32 acceptor_time_req
;
239 gss_cred_id_t
*output_cred_handle
;
240 gss_OID_set
*actual_mechs
;
241 OM_uint32
*initiator_time_rec
;
242 OM_uint32
*acceptor_time_rec
;
244 OM_uint32 status
, time_req
, time_rec
, temp_minor_status
;
246 gss_mechanism_ext mech_ext
;
247 gss_union_name_t union_name
= NULL
;
248 gss_union_cred_t union_cred
, new_union_cred
;
249 gss_name_t internal_name
= GSS_C_NO_NAME
;
250 gss_name_t allocated_name
= GSS_C_NO_NAME
;
251 gss_cred_id_t cred
= NULL
;
252 gss_OID new_mechs_array
= NULL
;
253 gss_cred_id_t
*new_cred_array
= NULL
;
255 /* check input parameters */
256 if (minor_status
== NULL
)
257 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
260 if (input_cred_handle
== GSS_C_NO_CREDENTIAL
&&
261 output_cred_handle
== NULL
)
262 return (GSS_S_CALL_INACCESSIBLE_WRITE
| GSS_S_NO_CRED
);
264 if (desired_name
== GSS_C_NO_NAME
)
265 return (GSS_S_BAD_NAME
);
266 union_name
= (gss_union_name_t
)desired_name
;
268 if (output_cred_handle
!= NULL
)
269 *output_cred_handle
= GSS_C_NO_CREDENTIAL
;
271 if (actual_mechs
!= NULL
)
272 *actual_mechs
= NULL
;
274 if (acceptor_time_rec
!= NULL
)
275 *acceptor_time_rec
= 0;
277 if (initiator_time_rec
!= NULL
)
278 *initiator_time_rec
= 0;
280 if ((mech
= __gss_get_mechanism(desired_mech
)) == NULL
)
281 return (GSS_S_BAD_MECH
);
283 if ((mech_ext
= __gss_get_mechanism_ext(desired_mech
)) == NULL
||
284 mech_ext
->gss_acquire_cred_with_password
== NULL
)
285 return (GSS_S_UNAVAILABLE
);
287 if (input_cred_handle
== GSS_C_NO_CREDENTIAL
) {
288 union_cred
= malloc(sizeof (gss_union_cred_desc
));
289 if (union_cred
== NULL
)
290 return (GSS_S_FAILURE
);
292 (void) memset(union_cred
, 0, sizeof (gss_union_cred_desc
));
295 union_cred
= (gss_union_cred_t
)input_cred_handle
;
296 if (__gss_get_mechanism_cred(union_cred
, desired_mech
) !=
298 return (GSS_S_DUPLICATE_ELEMENT
);
301 /* May need to create an MN */
302 if (union_name
->mech_type
&&
303 g_OID_equal(union_name
->mech_type
,
305 internal_name
= union_name
->mech_name
;
307 if (__gss_import_internal_name(minor_status
,
308 &mech
->mech_type
, union_name
,
309 &allocated_name
) != GSS_S_COMPLETE
)
310 return (GSS_S_BAD_NAME
);
311 internal_name
= allocated_name
;
314 if (cred_usage
== GSS_C_ACCEPT
)
315 time_req
= acceptor_time_req
;
316 else if (cred_usage
== GSS_C_INITIATE
)
317 time_req
= initiator_time_req
;
318 else if (cred_usage
== GSS_C_BOTH
)
319 time_req
= (acceptor_time_req
> initiator_time_req
) ?
320 acceptor_time_req
: initiator_time_req
;
322 status
= mech_ext
->gss_acquire_cred_with_password(mech
->context
,
323 minor_status
, internal_name
, password
, time_req
,
324 GSS_C_NULL_OID_SET
, cred_usage
, &cred
, NULL
,
327 if (status
!= GSS_S_COMPLETE
)
330 /* May need to set credential auxinfo strucutre */
331 if (union_cred
->auxinfo
.creation_time
== 0) {
332 union_cred
->auxinfo
.creation_time
= time(NULL
);
333 union_cred
->auxinfo
.time_rec
= time_rec
;
334 union_cred
->auxinfo
.cred_usage
= cred_usage
;
336 if ((status
= mech
->gss_display_name(mech
->context
,
337 &temp_minor_status
, internal_name
,
338 &union_cred
->auxinfo
.name
,
339 &union_cred
->auxinfo
.name_type
)) !=
344 /* Now add the new credential elements */
345 new_mechs_array
= (gss_OID
)
346 malloc(sizeof (gss_OID_desc
) * (union_cred
->count
+1));
348 new_cred_array
= (gss_cred_id_t
*)
349 malloc(sizeof (gss_cred_id_t
) * (union_cred
->count
+1));
351 if (!new_mechs_array
|| !new_cred_array
) {
352 status
= GSS_S_FAILURE
;
356 if (acceptor_time_rec
)
357 if (cred_usage
== GSS_C_ACCEPT
|| cred_usage
== GSS_C_BOTH
)
358 *acceptor_time_rec
= time_rec
;
359 if (initiator_time_rec
)
360 if (cred_usage
== GSS_C_INITIATE
|| cred_usage
== GSS_C_BOTH
)
361 *initiator_time_rec
= time_rec
;
364 * OK, expand the mechanism array and the credential array
366 (void) memcpy(new_mechs_array
, union_cred
->mechs_array
,
367 sizeof (gss_OID_desc
) * union_cred
->count
);
368 (void) memcpy(new_cred_array
, union_cred
->cred_array
,
369 sizeof (gss_cred_id_t
) * union_cred
->count
);
371 new_cred_array
[union_cred
->count
] = cred
;
372 if ((new_mechs_array
[union_cred
->count
].elements
=
373 malloc(mech
->mech_type
.length
)) == NULL
)
376 g_OID_copy(&new_mechs_array
[union_cred
->count
],
380 *actual_mechs
= create_actual_mechs(new_mechs_array
,
381 union_cred
->count
+ 1);
382 if (*actual_mechs
== NULL
) {
383 free(new_mechs_array
[union_cred
->count
].elements
);
388 if (output_cred_handle
== NULL
) {
389 free(union_cred
->mechs_array
);
390 free(union_cred
->cred_array
);
391 new_union_cred
= union_cred
;
393 new_union_cred
= malloc(sizeof (gss_union_cred_desc
));
394 if (new_union_cred
== NULL
) {
395 free(new_mechs_array
[union_cred
->count
].elements
);
398 *new_union_cred
= *union_cred
;
399 *output_cred_handle
= (gss_cred_id_t
)new_union_cred
;
402 new_union_cred
->mechs_array
= new_mechs_array
;
403 new_union_cred
->cred_array
= new_cred_array
;
404 new_union_cred
->count
++;
406 /* We're done with the internal name. Free it if we allocated it. */
409 (void) __gss_release_internal_name(&temp_minor_status
,
413 return (GSS_S_COMPLETE
);
417 free(new_mechs_array
);
419 free(new_cred_array
);
421 if (cred
!= NULL
&& mech
->gss_release_cred
)
422 mech
->gss_release_cred(mech
->context
,
423 &temp_minor_status
, &cred
);
426 (void) __gss_release_internal_name(&temp_minor_status
,
430 if (input_cred_handle
== GSS_C_NO_CREDENTIAL
&& union_cred
) {
431 if (union_cred
->auxinfo
.name
.value
)
432 free(union_cred
->auxinfo
.name
.value
);