10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53376Smp153739 * Common Development and Distribution License (the "License").
63376Smp153739 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*13132SGlenn.Barry@oracle.com * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate * glue routine for gss_acquire_cred
270Sstevel@tonic-gate */
280Sstevel@tonic-gate #include <mechglueP.h>
29*13132SGlenn.Barry@oracle.com #include "gssapiP_generic.h"
300Sstevel@tonic-gate #include <stdio.h>
310Sstevel@tonic-gate #ifdef HAVE_STDLIB_H
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #endif
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <errno.h>
360Sstevel@tonic-gate #include <time.h>
375053Sgtb
380Sstevel@tonic-gate /* local functions */
390Sstevel@tonic-gate static gss_OID_set create_actual_mechs(const gss_OID, int);
400Sstevel@tonic-gate
410Sstevel@tonic-gate static gss_OID_set
create_actual_mechs(mechs_array,count)420Sstevel@tonic-gate create_actual_mechs(mechs_array, count)
430Sstevel@tonic-gate const gss_OID mechs_array;
440Sstevel@tonic-gate int count;
450Sstevel@tonic-gate {
460Sstevel@tonic-gate gss_OID_set actual_mechs;
470Sstevel@tonic-gate int i;
480Sstevel@tonic-gate OM_uint32 minor;
490Sstevel@tonic-gate
500Sstevel@tonic-gate actual_mechs = (gss_OID_set) malloc(sizeof (gss_OID_set_desc));
510Sstevel@tonic-gate if (!actual_mechs)
520Sstevel@tonic-gate return (NULL);
530Sstevel@tonic-gate
540Sstevel@tonic-gate actual_mechs->elements = (gss_OID)
550Sstevel@tonic-gate malloc(sizeof (gss_OID_desc) * count);
560Sstevel@tonic-gate if (!actual_mechs->elements) {
570Sstevel@tonic-gate free(actual_mechs);
580Sstevel@tonic-gate return (NULL);
590Sstevel@tonic-gate }
600Sstevel@tonic-gate
610Sstevel@tonic-gate actual_mechs->count = 0;
620Sstevel@tonic-gate
630Sstevel@tonic-gate for (i = 0; i < count; i++) {
640Sstevel@tonic-gate actual_mechs->elements[i].elements = (void *)
650Sstevel@tonic-gate malloc(mechs_array[i].length);
660Sstevel@tonic-gate if (actual_mechs->elements[i].elements == NULL) {
670Sstevel@tonic-gate (void) gss_release_oid_set(&minor, &actual_mechs);
680Sstevel@tonic-gate return (NULL);
690Sstevel@tonic-gate }
700Sstevel@tonic-gate g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]);
710Sstevel@tonic-gate actual_mechs->count++;
720Sstevel@tonic-gate }
730Sstevel@tonic-gate
740Sstevel@tonic-gate return (actual_mechs);
750Sstevel@tonic-gate }
760Sstevel@tonic-gate
779698SPeter.Shoults@Sun.COM 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_cred_id_t * output_cred_handle,gss_OID_set * actual_mechs,OM_uint32 * time_rec)789698SPeter.Shoults@Sun.COM val_acq_cred_args(
79*13132SGlenn.Barry@oracle.com OM_uint32 *minor_status,
80*13132SGlenn.Barry@oracle.com /*LINTED*/
81*13132SGlenn.Barry@oracle.com gss_name_t desired_name,
82*13132SGlenn.Barry@oracle.com /*LINTED*/
83*13132SGlenn.Barry@oracle.com OM_uint32 time_req,
84*13132SGlenn.Barry@oracle.com /*LINTED*/
85*13132SGlenn.Barry@oracle.com gss_OID_set desired_mechs,
86*13132SGlenn.Barry@oracle.com int cred_usage,
87*13132SGlenn.Barry@oracle.com gss_cred_id_t *output_cred_handle,
88*13132SGlenn.Barry@oracle.com gss_OID_set *actual_mechs,
89*13132SGlenn.Barry@oracle.com OM_uint32 *time_rec)
909698SPeter.Shoults@Sun.COM {
919698SPeter.Shoults@Sun.COM
92*13132SGlenn.Barry@oracle.com /* Initialize outputs. */
939698SPeter.Shoults@Sun.COM
94*13132SGlenn.Barry@oracle.com if (minor_status != NULL)
95*13132SGlenn.Barry@oracle.com *minor_status = 0;
96*13132SGlenn.Barry@oracle.com
97*13132SGlenn.Barry@oracle.com if (output_cred_handle != NULL)
98*13132SGlenn.Barry@oracle.com *output_cred_handle = GSS_C_NO_CREDENTIAL;
999698SPeter.Shoults@Sun.COM
100*13132SGlenn.Barry@oracle.com if (actual_mechs != NULL)
101*13132SGlenn.Barry@oracle.com *actual_mechs = GSS_C_NULL_OID_SET;
1029698SPeter.Shoults@Sun.COM
103*13132SGlenn.Barry@oracle.com if (time_rec != NULL)
104*13132SGlenn.Barry@oracle.com *time_rec = 0;
105*13132SGlenn.Barry@oracle.com
106*13132SGlenn.Barry@oracle.com /* Validate arguments. */
1079698SPeter.Shoults@Sun.COM
108*13132SGlenn.Barry@oracle.com if (minor_status == NULL)
109*13132SGlenn.Barry@oracle.com return (GSS_S_CALL_INACCESSIBLE_WRITE);
1109698SPeter.Shoults@Sun.COM
111*13132SGlenn.Barry@oracle.com if (output_cred_handle == NULL)
112*13132SGlenn.Barry@oracle.com return (GSS_S_CALL_INACCESSIBLE_WRITE);
1139698SPeter.Shoults@Sun.COM
114*13132SGlenn.Barry@oracle.com if (cred_usage != GSS_C_ACCEPT
115*13132SGlenn.Barry@oracle.com && cred_usage != GSS_C_INITIATE
116*13132SGlenn.Barry@oracle.com && cred_usage != GSS_C_BOTH) {
117*13132SGlenn.Barry@oracle.com if (minor_status) {
118*13132SGlenn.Barry@oracle.com *minor_status = EINVAL;
119*13132SGlenn.Barry@oracle.com map_errcode(minor_status);
120*13132SGlenn.Barry@oracle.com }
121*13132SGlenn.Barry@oracle.com return GSS_S_FAILURE;
122*13132SGlenn.Barry@oracle.com }
1239698SPeter.Shoults@Sun.COM
124*13132SGlenn.Barry@oracle.com return (GSS_S_COMPLETE);
1259698SPeter.Shoults@Sun.COM }
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate OM_uint32
gss_acquire_cred(minor_status,desired_name,time_req,desired_mechs,cred_usage,output_cred_handle,actual_mechs,time_rec)1280Sstevel@tonic-gate gss_acquire_cred(minor_status,
1290Sstevel@tonic-gate desired_name,
1300Sstevel@tonic-gate time_req,
1310Sstevel@tonic-gate desired_mechs,
1320Sstevel@tonic-gate cred_usage,
1330Sstevel@tonic-gate output_cred_handle,
1340Sstevel@tonic-gate actual_mechs,
1350Sstevel@tonic-gate time_rec)
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate OM_uint32 * minor_status;
1380Sstevel@tonic-gate const gss_name_t desired_name;
1390Sstevel@tonic-gate OM_uint32 time_req;
1400Sstevel@tonic-gate const gss_OID_set desired_mechs;
1410Sstevel@tonic-gate int cred_usage;
1420Sstevel@tonic-gate gss_cred_id_t *output_cred_handle;
1430Sstevel@tonic-gate gss_OID_set * actual_mechs;
1440Sstevel@tonic-gate OM_uint32 * time_rec;
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate OM_uint32 major = GSS_S_FAILURE;
1480Sstevel@tonic-gate OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE;
1490Sstevel@tonic-gate gss_OID_set_desc default_OID_set;
1500Sstevel@tonic-gate gss_OID_set mechs;
1510Sstevel@tonic-gate gss_OID_desc default_OID;
1520Sstevel@tonic-gate gss_mechanism mech;
153*13132SGlenn.Barry@oracle.com unsigned int i;
1540Sstevel@tonic-gate gss_union_cred_t creds;
1550Sstevel@tonic-gate
1569698SPeter.Shoults@Sun.COM major = val_acq_cred_args(minor_status,
157*13132SGlenn.Barry@oracle.com desired_name,
158*13132SGlenn.Barry@oracle.com time_req,
159*13132SGlenn.Barry@oracle.com desired_mechs,
160*13132SGlenn.Barry@oracle.com cred_usage,
1619698SPeter.Shoults@Sun.COM output_cred_handle,
1629698SPeter.Shoults@Sun.COM actual_mechs,
1639698SPeter.Shoults@Sun.COM time_rec);
1649698SPeter.Shoults@Sun.COM if (major != GSS_S_COMPLETE)
1659698SPeter.Shoults@Sun.COM return (major);
1660Sstevel@tonic-gate
1679698SPeter.Shoults@Sun.COM /* Initial value needed below. */
1689698SPeter.Shoults@Sun.COM major = GSS_S_FAILURE;
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate /*
1710Sstevel@tonic-gate * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an
1720Sstevel@tonic-gate * appropriate default. We use the first mechanism in the
1730Sstevel@tonic-gate * mechansim list as the default. This set is created with
1740Sstevel@tonic-gate * statics thus needs not be freed
1750Sstevel@tonic-gate */
1760Sstevel@tonic-gate if (desired_mechs == GSS_C_NULL_OID_SET) {
1770Sstevel@tonic-gate mech = __gss_get_mechanism(NULL);
1780Sstevel@tonic-gate if (mech == NULL)
1790Sstevel@tonic-gate return (GSS_S_BAD_MECH);
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate mechs = &default_OID_set;
1820Sstevel@tonic-gate default_OID_set.count = 1;
1830Sstevel@tonic-gate default_OID_set.elements = &default_OID;
1840Sstevel@tonic-gate default_OID.length = mech->mech_type.length;
1850Sstevel@tonic-gate default_OID.elements = mech->mech_type.elements;
1860Sstevel@tonic-gate } else
1870Sstevel@tonic-gate mechs = desired_mechs;
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate if (mechs->count == NULL)
1900Sstevel@tonic-gate return (GSS_S_BAD_MECH);
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate /* allocate the output credential structure */
1930Sstevel@tonic-gate creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc));
1940Sstevel@tonic-gate if (creds == NULL)
1950Sstevel@tonic-gate return (GSS_S_FAILURE);
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate /* initialize to 0s */
1980Sstevel@tonic-gate (void) memset(creds, 0, sizeof (gss_union_cred_desc));
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate /* for each requested mech attempt to obtain a credential */
2010Sstevel@tonic-gate for (i = 0; i < mechs->count; i++) {
2020Sstevel@tonic-gate major = gss_add_cred(minor_status, (gss_cred_id_t)creds,
2030Sstevel@tonic-gate desired_name,
2040Sstevel@tonic-gate &mechs->elements[i],
2050Sstevel@tonic-gate cred_usage, time_req, time_req, NULL,
2060Sstevel@tonic-gate NULL, &initTimeOut, &acceptTimeOut);
2070Sstevel@tonic-gate if (major == GSS_S_COMPLETE) {
2080Sstevel@tonic-gate /* update the credential's time */
2090Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT) {
2100Sstevel@tonic-gate if (outTime > acceptTimeOut)
2110Sstevel@tonic-gate outTime = acceptTimeOut;
2120Sstevel@tonic-gate } else if (cred_usage == GSS_C_INITIATE) {
2130Sstevel@tonic-gate if (outTime > initTimeOut)
2140Sstevel@tonic-gate outTime = initTimeOut;
2150Sstevel@tonic-gate } else {
2160Sstevel@tonic-gate /*
2170Sstevel@tonic-gate * time_rec is the lesser of the
2180Sstevel@tonic-gate * init/accept times
2190Sstevel@tonic-gate */
2200Sstevel@tonic-gate if (initTimeOut > acceptTimeOut)
2210Sstevel@tonic-gate outTime = (outTime > acceptTimeOut) ?
2220Sstevel@tonic-gate acceptTimeOut : outTime;
2230Sstevel@tonic-gate else
2240Sstevel@tonic-gate outTime = (outTime > initTimeOut) ?
2250Sstevel@tonic-gate initTimeOut : outTime;
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate } /* for */
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate /* ensure that we have at least one credential element */
2310Sstevel@tonic-gate if (creds->count < 1) {
2320Sstevel@tonic-gate free(creds);
2330Sstevel@tonic-gate return (major);
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate /*
2370Sstevel@tonic-gate * fill in output parameters
2380Sstevel@tonic-gate * setup the actual mechs output parameter
2390Sstevel@tonic-gate */
2400Sstevel@tonic-gate if (actual_mechs != NULL) {
2410Sstevel@tonic-gate if ((*actual_mechs = create_actual_mechs(creds->mechs_array,
2420Sstevel@tonic-gate creds->count)) == NULL) {
2430Sstevel@tonic-gate (void) gss_release_cred(minor_status,
2440Sstevel@tonic-gate (gss_cred_id_t *)&creds);
2450Sstevel@tonic-gate *minor_status = 0;
2460Sstevel@tonic-gate return (GSS_S_FAILURE);
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate if (time_rec)
2510Sstevel@tonic-gate *time_rec = outTime;
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate *output_cred_handle = (gss_cred_id_t)creds;
2550Sstevel@tonic-gate return (GSS_S_COMPLETE);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate
2589698SPeter.Shoults@Sun.COM 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,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)2599698SPeter.Shoults@Sun.COM val_add_cred_args(
2609698SPeter.Shoults@Sun.COM OM_uint32 *minor_status,
2619698SPeter.Shoults@Sun.COM gss_cred_id_t input_cred_handle,
262*13132SGlenn.Barry@oracle.com /*LINTED*/
263*13132SGlenn.Barry@oracle.com gss_name_t desired_name,
264*13132SGlenn.Barry@oracle.com /*LINTED*/
265*13132SGlenn.Barry@oracle.com gss_OID desired_mech,
266*13132SGlenn.Barry@oracle.com gss_cred_usage_t cred_usage,
267*13132SGlenn.Barry@oracle.com /*LINTED*/
268*13132SGlenn.Barry@oracle.com OM_uint32 initiator_time_req,
269*13132SGlenn.Barry@oracle.com /*LINTED*/
270*13132SGlenn.Barry@oracle.com OM_uint32 acceptor_time_req,
2719698SPeter.Shoults@Sun.COM gss_cred_id_t *output_cred_handle,
2729698SPeter.Shoults@Sun.COM gss_OID_set *actual_mechs,
2739698SPeter.Shoults@Sun.COM OM_uint32 *initiator_time_rec,
2749698SPeter.Shoults@Sun.COM OM_uint32 *acceptor_time_rec)
2759698SPeter.Shoults@Sun.COM {
2769698SPeter.Shoults@Sun.COM
2779698SPeter.Shoults@Sun.COM /* Initialize outputs. */
2789698SPeter.Shoults@Sun.COM
2799698SPeter.Shoults@Sun.COM if (minor_status != NULL)
2809698SPeter.Shoults@Sun.COM *minor_status = 0;
2819698SPeter.Shoults@Sun.COM
2829698SPeter.Shoults@Sun.COM if (output_cred_handle != NULL)
2839698SPeter.Shoults@Sun.COM *output_cred_handle = GSS_C_NO_CREDENTIAL;
2849698SPeter.Shoults@Sun.COM
2859698SPeter.Shoults@Sun.COM if (actual_mechs != NULL)
2869698SPeter.Shoults@Sun.COM *actual_mechs = GSS_C_NO_OID_SET;
2879698SPeter.Shoults@Sun.COM
2889698SPeter.Shoults@Sun.COM if (acceptor_time_rec != NULL)
2899698SPeter.Shoults@Sun.COM *acceptor_time_rec = 0;
2909698SPeter.Shoults@Sun.COM
2919698SPeter.Shoults@Sun.COM if (initiator_time_rec != NULL)
2929698SPeter.Shoults@Sun.COM *initiator_time_rec = 0;
2939698SPeter.Shoults@Sun.COM /* Validate arguments. */
2949698SPeter.Shoults@Sun.COM
2959698SPeter.Shoults@Sun.COM if (minor_status == NULL)
2969698SPeter.Shoults@Sun.COM return (GSS_S_CALL_INACCESSIBLE_WRITE);
2979698SPeter.Shoults@Sun.COM
2989698SPeter.Shoults@Sun.COM if (input_cred_handle == GSS_C_NO_CREDENTIAL &&
299*13132SGlenn.Barry@oracle.com output_cred_handle == NULL)
300*13132SGlenn.Barry@oracle.com return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
3019698SPeter.Shoults@Sun.COM
302*13132SGlenn.Barry@oracle.com if (cred_usage != GSS_C_ACCEPT
303*13132SGlenn.Barry@oracle.com && cred_usage != GSS_C_INITIATE
304*13132SGlenn.Barry@oracle.com && cred_usage != GSS_C_BOTH) {
305*13132SGlenn.Barry@oracle.com if (minor_status) {
306*13132SGlenn.Barry@oracle.com *minor_status = EINVAL;
307*13132SGlenn.Barry@oracle.com map_errcode(minor_status);
308*13132SGlenn.Barry@oracle.com }
309*13132SGlenn.Barry@oracle.com return GSS_S_FAILURE;
310*13132SGlenn.Barry@oracle.com }
3119698SPeter.Shoults@Sun.COM
3129698SPeter.Shoults@Sun.COM return (GSS_S_COMPLETE);
3139698SPeter.Shoults@Sun.COM }
3149698SPeter.Shoults@Sun.COM
3150Sstevel@tonic-gate /* V2 INTERFACE */
3160Sstevel@tonic-gate OM_uint32
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)3170Sstevel@tonic-gate gss_add_cred(minor_status, input_cred_handle,
3180Sstevel@tonic-gate desired_name, desired_mech, cred_usage,
3190Sstevel@tonic-gate initiator_time_req, acceptor_time_req,
3200Sstevel@tonic-gate output_cred_handle, actual_mechs,
3210Sstevel@tonic-gate initiator_time_rec, acceptor_time_rec)
3220Sstevel@tonic-gate OM_uint32 *minor_status;
3230Sstevel@tonic-gate const gss_cred_id_t input_cred_handle;
3240Sstevel@tonic-gate const gss_name_t desired_name;
3250Sstevel@tonic-gate const gss_OID desired_mech;
3260Sstevel@tonic-gate gss_cred_usage_t cred_usage;
3270Sstevel@tonic-gate OM_uint32 initiator_time_req;
3280Sstevel@tonic-gate OM_uint32 acceptor_time_req;
3290Sstevel@tonic-gate gss_cred_id_t *output_cred_handle;
3300Sstevel@tonic-gate gss_OID_set *actual_mechs;
3310Sstevel@tonic-gate OM_uint32 *initiator_time_rec;
3320Sstevel@tonic-gate OM_uint32 *acceptor_time_rec;
3330Sstevel@tonic-gate {
3340Sstevel@tonic-gate OM_uint32 status, time_req, time_rec, temp_minor_status;
3350Sstevel@tonic-gate gss_mechanism mech;
3360Sstevel@tonic-gate gss_union_name_t union_name = NULL;
3370Sstevel@tonic-gate gss_union_cred_t union_cred, new_union_cred;
3380Sstevel@tonic-gate gss_name_t internal_name = GSS_C_NO_NAME;
3390Sstevel@tonic-gate gss_name_t allocated_name = GSS_C_NO_NAME;
3400Sstevel@tonic-gate gss_cred_id_t cred = NULL;
3410Sstevel@tonic-gate gss_OID new_mechs_array = NULL;
3420Sstevel@tonic-gate gss_cred_id_t *new_cred_array = NULL;
3430Sstevel@tonic-gate
3449698SPeter.Shoults@Sun.COM status = val_add_cred_args(minor_status,
3459698SPeter.Shoults@Sun.COM input_cred_handle,
346*13132SGlenn.Barry@oracle.com desired_name,
347*13132SGlenn.Barry@oracle.com desired_mech,
348*13132SGlenn.Barry@oracle.com cred_usage,
349*13132SGlenn.Barry@oracle.com initiator_time_req,
350*13132SGlenn.Barry@oracle.com acceptor_time_req,
3519698SPeter.Shoults@Sun.COM output_cred_handle,
3529698SPeter.Shoults@Sun.COM actual_mechs,
3539698SPeter.Shoults@Sun.COM initiator_time_rec,
3549698SPeter.Shoults@Sun.COM acceptor_time_rec);
3559698SPeter.Shoults@Sun.COM if (status != GSS_S_COMPLETE)
3569698SPeter.Shoults@Sun.COM return (status);
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate mech = __gss_get_mechanism(desired_mech);
3590Sstevel@tonic-gate if (!mech)
3600Sstevel@tonic-gate return (GSS_S_BAD_MECH);
3610Sstevel@tonic-gate else if (!mech->gss_acquire_cred)
3620Sstevel@tonic-gate return (GSS_S_UNAVAILABLE);
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
3650Sstevel@tonic-gate union_cred = malloc(sizeof (gss_union_cred_desc));
3660Sstevel@tonic-gate if (union_cred == NULL)
3670Sstevel@tonic-gate return (GSS_S_FAILURE);
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate (void) memset(union_cred, 0, sizeof (gss_union_cred_desc));
370160Swyllys } else {
371160Swyllys /* Input Cred is non-NULL */
372160Swyllys union_cred = (gss_union_cred_t)input_cred_handle;
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate if (__gss_get_mechanism_cred(union_cred, desired_mech) !=
375160Swyllys GSS_C_NO_CREDENTIAL) {
376160Swyllys status = GSS_S_DUPLICATE_ELEMENT;
377160Swyllys goto errout;
378160Swyllys }
3790Sstevel@tonic-gate
380160Swyllys /*
381160Swyllys * If no name was given, determine the name from the
382160Swyllys * existing credential.
383160Swyllys */
384160Swyllys if (desired_name == GSS_C_NO_NAME) {
385160Swyllys if (gss_import_name(minor_status,
386160Swyllys &union_cred->auxinfo.name,
387160Swyllys union_cred->auxinfo.name_type,
388160Swyllys &allocated_name) == GSS_S_COMPLETE &&
389160Swyllys (gss_canonicalize_name(minor_status,
390160Swyllys allocated_name,
391160Swyllys &mech->mech_type,
392160Swyllys NULL) == GSS_S_COMPLETE)) {
3930Sstevel@tonic-gate internal_name = allocated_name;
3940Sstevel@tonic-gate }
395160Swyllys } /* else, get the name from the desired_name below */
396160Swyllys }
397160Swyllys if (desired_name != GSS_C_NO_NAME) {
398160Swyllys /* may need to create a mechanism specific name */
399160Swyllys union_name = (gss_union_name_t)desired_name;
400160Swyllys
401160Swyllys if (union_name->mech_type &&
402160Swyllys g_OID_equal(union_name->mech_type,
403160Swyllys &mech->mech_type))
404160Swyllys internal_name = union_name->mech_name;
405160Swyllys else {
406160Swyllys if (__gss_import_internal_name(minor_status,
407160Swyllys &mech->mech_type, union_name,
408160Swyllys &allocated_name) != GSS_S_COMPLETE) {
409160Swyllys status = GSS_S_BAD_NAME;
410160Swyllys goto errout;
411160Swyllys }
412160Swyllys internal_name = allocated_name;
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT)
4170Sstevel@tonic-gate time_req = acceptor_time_req;
4180Sstevel@tonic-gate else if (cred_usage == GSS_C_INITIATE)
4190Sstevel@tonic-gate time_req = initiator_time_req;
4200Sstevel@tonic-gate else if (cred_usage == GSS_C_BOTH)
4210Sstevel@tonic-gate time_req = (acceptor_time_req > initiator_time_req) ?
4220Sstevel@tonic-gate acceptor_time_req : initiator_time_req;
423*13132SGlenn.Barry@oracle.com else
424*13132SGlenn.Barry@oracle.com time_req = 0;
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate status = mech->gss_acquire_cred(mech->context, minor_status,
4270Sstevel@tonic-gate internal_name, time_req,
4280Sstevel@tonic-gate GSS_C_NULL_OID_SET, cred_usage,
4290Sstevel@tonic-gate &cred, NULL, &time_rec);
4300Sstevel@tonic-gate
431*13132SGlenn.Barry@oracle.com if (status != GSS_S_COMPLETE) {
432*13132SGlenn.Barry@oracle.com map_error(minor_status, mech);
4330Sstevel@tonic-gate goto errout;
434*13132SGlenn.Barry@oracle.com }
4350Sstevel@tonic-gate
436160Swyllys /* may need to set credential auxinfo structure */
4370Sstevel@tonic-gate if (union_cred->auxinfo.creation_time == 0) {
4380Sstevel@tonic-gate union_cred->auxinfo.creation_time = time(NULL);
4390Sstevel@tonic-gate union_cred->auxinfo.time_rec = time_rec;
4400Sstevel@tonic-gate union_cred->auxinfo.cred_usage = cred_usage;
4410Sstevel@tonic-gate
4423376Smp153739 /*
4433376Smp153739 * If internal_name is GSS_C_NO_NAME a cred with no associated
4443376Smp153739 * name was requested: don't set auxinfo.name or auxinfo.name_type.
4453376Smp153739 */
4463376Smp153739 if (internal_name != GSS_C_NO_NAME) {
4473376Smp153739 if ((status = mech->gss_display_name(mech->context,
4483376Smp153739 &temp_minor_status, internal_name,
4493376Smp153739 &union_cred->auxinfo.name,
4503376Smp153739 &union_cred->auxinfo.name_type)) !=
4513376Smp153739 GSS_S_COMPLETE)
4520Sstevel@tonic-gate goto errout;
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate /* now add the new credential elements */
4570Sstevel@tonic-gate new_mechs_array = (gss_OID)
4580Sstevel@tonic-gate malloc(sizeof (gss_OID_desc) * (union_cred->count+1));
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate new_cred_array = (gss_cred_id_t *)
4610Sstevel@tonic-gate malloc(sizeof (gss_cred_id_t) * (union_cred->count+1));
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate if (!new_mechs_array || !new_cred_array) {
4640Sstevel@tonic-gate status = GSS_S_FAILURE;
4650Sstevel@tonic-gate goto errout;
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate
4680Sstevel@tonic-gate if (acceptor_time_rec)
4690Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH)
4700Sstevel@tonic-gate *acceptor_time_rec = time_rec;
4710Sstevel@tonic-gate if (initiator_time_rec)
4720Sstevel@tonic-gate if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH)
4730Sstevel@tonic-gate *initiator_time_rec = time_rec;
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate /*
4760Sstevel@tonic-gate * OK, expand the mechanism array and the credential array
4770Sstevel@tonic-gate */
4780Sstevel@tonic-gate (void) memcpy(new_mechs_array, union_cred->mechs_array,
4790Sstevel@tonic-gate sizeof (gss_OID_desc) * union_cred->count);
4800Sstevel@tonic-gate (void) memcpy(new_cred_array, union_cred->cred_array,
4810Sstevel@tonic-gate sizeof (gss_cred_id_t) * union_cred->count);
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate new_cred_array[union_cred->count] = cred;
4840Sstevel@tonic-gate if ((new_mechs_array[union_cred->count].elements =
4850Sstevel@tonic-gate malloc(mech->mech_type.length)) == NULL)
4860Sstevel@tonic-gate goto errout;
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate g_OID_copy(&new_mechs_array[union_cred->count],
4890Sstevel@tonic-gate &mech->mech_type);
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate if (actual_mechs) {
4920Sstevel@tonic-gate *actual_mechs = create_actual_mechs(new_mechs_array,
4930Sstevel@tonic-gate union_cred->count + 1);
4940Sstevel@tonic-gate if (*actual_mechs == NULL) {
4950Sstevel@tonic-gate free(new_mechs_array[union_cred->count].elements);
4960Sstevel@tonic-gate goto errout;
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate if (output_cred_handle == NULL) {
5010Sstevel@tonic-gate free(union_cred->mechs_array);
5020Sstevel@tonic-gate free(union_cred->cred_array);
5030Sstevel@tonic-gate new_union_cred = union_cred;
5040Sstevel@tonic-gate } else {
5050Sstevel@tonic-gate new_union_cred = malloc(sizeof (gss_union_cred_desc));
5060Sstevel@tonic-gate if (new_union_cred == NULL) {
5070Sstevel@tonic-gate free(new_mechs_array[union_cred->count].elements);
5080Sstevel@tonic-gate goto errout;
5090Sstevel@tonic-gate }
5100Sstevel@tonic-gate *new_union_cred = *union_cred;
5110Sstevel@tonic-gate *output_cred_handle = (gss_cred_id_t)new_union_cred;
5120Sstevel@tonic-gate }
5130Sstevel@tonic-gate
5140Sstevel@tonic-gate new_union_cred->mechs_array = new_mechs_array;
5150Sstevel@tonic-gate new_union_cred->cred_array = new_cred_array;
5160Sstevel@tonic-gate new_union_cred->count++;
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate /* We're done with the internal name. Free it if we allocated it. */
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate if (allocated_name)
5210Sstevel@tonic-gate (void) __gss_release_internal_name(&temp_minor_status,
5220Sstevel@tonic-gate &mech->mech_type,
5230Sstevel@tonic-gate &allocated_name);
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate return (GSS_S_COMPLETE);
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate errout:
5280Sstevel@tonic-gate if (new_mechs_array)
5290Sstevel@tonic-gate free(new_mechs_array);
5300Sstevel@tonic-gate if (new_cred_array)
5310Sstevel@tonic-gate free(new_cred_array);
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate if (cred != NULL && mech->gss_release_cred)
5340Sstevel@tonic-gate mech->gss_release_cred(mech->context,
5350Sstevel@tonic-gate &temp_minor_status, &cred);
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate if (allocated_name)
5380Sstevel@tonic-gate (void) __gss_release_internal_name(&temp_minor_status,
5390Sstevel@tonic-gate &mech->mech_type,
5400Sstevel@tonic-gate &allocated_name);
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) {
5430Sstevel@tonic-gate if (union_cred->auxinfo.name.value)
5440Sstevel@tonic-gate free(union_cred->auxinfo.name.value);
5450Sstevel@tonic-gate free(union_cred);
5460Sstevel@tonic-gate }
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate return (status);
5490Sstevel@tonic-gate }
550