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 /* 223376Smp153739 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * glue routine for gss_acquire_cred 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate #include <mechglueP.h> 320Sstevel@tonic-gate #include <stdio.h> 330Sstevel@tonic-gate #ifdef HAVE_STDLIB_H 340Sstevel@tonic-gate #include <stdlib.h> 350Sstevel@tonic-gate #endif 360Sstevel@tonic-gate #include <string.h> 370Sstevel@tonic-gate #include <errno.h> 380Sstevel@tonic-gate #include <time.h> 39*5053Sgtb 400Sstevel@tonic-gate /* local functions */ 410Sstevel@tonic-gate static gss_OID_set create_actual_mechs(const gss_OID, int); 420Sstevel@tonic-gate 430Sstevel@tonic-gate static gss_OID_set 440Sstevel@tonic-gate create_actual_mechs(mechs_array, count) 450Sstevel@tonic-gate const gss_OID mechs_array; 460Sstevel@tonic-gate int count; 470Sstevel@tonic-gate { 480Sstevel@tonic-gate gss_OID_set actual_mechs; 490Sstevel@tonic-gate int i; 500Sstevel@tonic-gate OM_uint32 minor; 510Sstevel@tonic-gate 520Sstevel@tonic-gate actual_mechs = (gss_OID_set) malloc(sizeof (gss_OID_set_desc)); 530Sstevel@tonic-gate if (!actual_mechs) 540Sstevel@tonic-gate return (NULL); 550Sstevel@tonic-gate 560Sstevel@tonic-gate actual_mechs->elements = (gss_OID) 570Sstevel@tonic-gate malloc(sizeof (gss_OID_desc) * count); 580Sstevel@tonic-gate if (!actual_mechs->elements) { 590Sstevel@tonic-gate free(actual_mechs); 600Sstevel@tonic-gate return (NULL); 610Sstevel@tonic-gate } 620Sstevel@tonic-gate 630Sstevel@tonic-gate actual_mechs->count = 0; 640Sstevel@tonic-gate 650Sstevel@tonic-gate for (i = 0; i < count; i++) { 660Sstevel@tonic-gate actual_mechs->elements[i].elements = (void *) 670Sstevel@tonic-gate malloc(mechs_array[i].length); 680Sstevel@tonic-gate if (actual_mechs->elements[i].elements == NULL) { 690Sstevel@tonic-gate (void) gss_release_oid_set(&minor, &actual_mechs); 700Sstevel@tonic-gate return (NULL); 710Sstevel@tonic-gate } 720Sstevel@tonic-gate g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]); 730Sstevel@tonic-gate actual_mechs->count++; 740Sstevel@tonic-gate } 750Sstevel@tonic-gate 760Sstevel@tonic-gate return (actual_mechs); 770Sstevel@tonic-gate } 780Sstevel@tonic-gate 790Sstevel@tonic-gate 800Sstevel@tonic-gate OM_uint32 810Sstevel@tonic-gate gss_acquire_cred(minor_status, 820Sstevel@tonic-gate desired_name, 830Sstevel@tonic-gate time_req, 840Sstevel@tonic-gate desired_mechs, 850Sstevel@tonic-gate cred_usage, 860Sstevel@tonic-gate output_cred_handle, 870Sstevel@tonic-gate actual_mechs, 880Sstevel@tonic-gate time_rec) 890Sstevel@tonic-gate 900Sstevel@tonic-gate OM_uint32 * minor_status; 910Sstevel@tonic-gate const gss_name_t desired_name; 920Sstevel@tonic-gate OM_uint32 time_req; 930Sstevel@tonic-gate const gss_OID_set desired_mechs; 940Sstevel@tonic-gate int cred_usage; 950Sstevel@tonic-gate gss_cred_id_t *output_cred_handle; 960Sstevel@tonic-gate gss_OID_set * actual_mechs; 970Sstevel@tonic-gate OM_uint32 * time_rec; 980Sstevel@tonic-gate 990Sstevel@tonic-gate { 1000Sstevel@tonic-gate OM_uint32 major = GSS_S_FAILURE; 1010Sstevel@tonic-gate OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE; 1020Sstevel@tonic-gate gss_OID_set_desc default_OID_set; 1030Sstevel@tonic-gate gss_OID_set mechs; 1040Sstevel@tonic-gate gss_OID_desc default_OID; 1050Sstevel@tonic-gate gss_mechanism mech; 1060Sstevel@tonic-gate int i; 1070Sstevel@tonic-gate gss_union_cred_t creds; 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate /* start by checking parameters */ 1100Sstevel@tonic-gate if (!minor_status) 1110Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 1120Sstevel@tonic-gate *minor_status = 0; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate if (!output_cred_handle) 1150Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate *output_cred_handle = GSS_C_NO_CREDENTIAL; 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate /* Set output parameters to NULL for now */ 1200Sstevel@tonic-gate if (actual_mechs) 1210Sstevel@tonic-gate *actual_mechs = GSS_C_NULL_OID_SET; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate if (time_rec) 1240Sstevel@tonic-gate *time_rec = 0; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate /* 1270Sstevel@tonic-gate * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an 1280Sstevel@tonic-gate * appropriate default. We use the first mechanism in the 1290Sstevel@tonic-gate * mechansim list as the default. This set is created with 1300Sstevel@tonic-gate * statics thus needs not be freed 1310Sstevel@tonic-gate */ 1320Sstevel@tonic-gate if (desired_mechs == GSS_C_NULL_OID_SET) { 1330Sstevel@tonic-gate mech = __gss_get_mechanism(NULL); 1340Sstevel@tonic-gate if (mech == NULL) 1350Sstevel@tonic-gate return (GSS_S_BAD_MECH); 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate mechs = &default_OID_set; 1380Sstevel@tonic-gate default_OID_set.count = 1; 1390Sstevel@tonic-gate default_OID_set.elements = &default_OID; 1400Sstevel@tonic-gate default_OID.length = mech->mech_type.length; 1410Sstevel@tonic-gate default_OID.elements = mech->mech_type.elements; 1420Sstevel@tonic-gate } else 1430Sstevel@tonic-gate mechs = desired_mechs; 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate if (mechs->count == NULL) 1460Sstevel@tonic-gate return (GSS_S_BAD_MECH); 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate /* allocate the output credential structure */ 1490Sstevel@tonic-gate creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc)); 1500Sstevel@tonic-gate if (creds == NULL) 1510Sstevel@tonic-gate return (GSS_S_FAILURE); 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate /* initialize to 0s */ 1540Sstevel@tonic-gate (void) memset(creds, 0, sizeof (gss_union_cred_desc)); 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate /* for each requested mech attempt to obtain a credential */ 1570Sstevel@tonic-gate for (i = 0; i < mechs->count; i++) { 1580Sstevel@tonic-gate major = gss_add_cred(minor_status, (gss_cred_id_t)creds, 1590Sstevel@tonic-gate desired_name, 1600Sstevel@tonic-gate &mechs->elements[i], 1610Sstevel@tonic-gate cred_usage, time_req, time_req, NULL, 1620Sstevel@tonic-gate NULL, &initTimeOut, &acceptTimeOut); 1630Sstevel@tonic-gate if (major == GSS_S_COMPLETE) { 1640Sstevel@tonic-gate /* update the credential's time */ 1650Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT) { 1660Sstevel@tonic-gate if (outTime > acceptTimeOut) 1670Sstevel@tonic-gate outTime = acceptTimeOut; 1680Sstevel@tonic-gate } else if (cred_usage == GSS_C_INITIATE) { 1690Sstevel@tonic-gate if (outTime > initTimeOut) 1700Sstevel@tonic-gate outTime = initTimeOut; 1710Sstevel@tonic-gate } else { 1720Sstevel@tonic-gate /* 1730Sstevel@tonic-gate * time_rec is the lesser of the 1740Sstevel@tonic-gate * init/accept times 1750Sstevel@tonic-gate */ 1760Sstevel@tonic-gate if (initTimeOut > acceptTimeOut) 1770Sstevel@tonic-gate outTime = (outTime > acceptTimeOut) ? 1780Sstevel@tonic-gate acceptTimeOut : outTime; 1790Sstevel@tonic-gate else 1800Sstevel@tonic-gate outTime = (outTime > initTimeOut) ? 1810Sstevel@tonic-gate initTimeOut : outTime; 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate } 1840Sstevel@tonic-gate } /* for */ 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* ensure that we have at least one credential element */ 1870Sstevel@tonic-gate if (creds->count < 1) { 1880Sstevel@tonic-gate free(creds); 1890Sstevel@tonic-gate return (major); 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate /* 1930Sstevel@tonic-gate * fill in output parameters 1940Sstevel@tonic-gate * setup the actual mechs output parameter 1950Sstevel@tonic-gate */ 1960Sstevel@tonic-gate if (actual_mechs != NULL) { 1970Sstevel@tonic-gate if ((*actual_mechs = create_actual_mechs(creds->mechs_array, 1980Sstevel@tonic-gate creds->count)) == NULL) { 1990Sstevel@tonic-gate (void) gss_release_cred(minor_status, 2000Sstevel@tonic-gate (gss_cred_id_t *)&creds); 2010Sstevel@tonic-gate *minor_status = 0; 2020Sstevel@tonic-gate return (GSS_S_FAILURE); 2030Sstevel@tonic-gate } 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate if (time_rec) 2070Sstevel@tonic-gate *time_rec = outTime; 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate *output_cred_handle = (gss_cred_id_t)creds; 2110Sstevel@tonic-gate return (GSS_S_COMPLETE); 2120Sstevel@tonic-gate } 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate /* V2 INTERFACE */ 2150Sstevel@tonic-gate OM_uint32 2160Sstevel@tonic-gate gss_add_cred(minor_status, input_cred_handle, 2170Sstevel@tonic-gate desired_name, desired_mech, cred_usage, 2180Sstevel@tonic-gate initiator_time_req, acceptor_time_req, 2190Sstevel@tonic-gate output_cred_handle, actual_mechs, 2200Sstevel@tonic-gate initiator_time_rec, acceptor_time_rec) 2210Sstevel@tonic-gate OM_uint32 *minor_status; 2220Sstevel@tonic-gate const gss_cred_id_t input_cred_handle; 2230Sstevel@tonic-gate const gss_name_t desired_name; 2240Sstevel@tonic-gate const gss_OID desired_mech; 2250Sstevel@tonic-gate gss_cred_usage_t cred_usage; 2260Sstevel@tonic-gate OM_uint32 initiator_time_req; 2270Sstevel@tonic-gate OM_uint32 acceptor_time_req; 2280Sstevel@tonic-gate gss_cred_id_t *output_cred_handle; 2290Sstevel@tonic-gate gss_OID_set *actual_mechs; 2300Sstevel@tonic-gate OM_uint32 *initiator_time_rec; 2310Sstevel@tonic-gate OM_uint32 *acceptor_time_rec; 2320Sstevel@tonic-gate { 2330Sstevel@tonic-gate OM_uint32 status, time_req, time_rec, temp_minor_status; 2340Sstevel@tonic-gate gss_mechanism mech; 2350Sstevel@tonic-gate gss_union_name_t union_name = NULL; 2360Sstevel@tonic-gate gss_union_cred_t union_cred, new_union_cred; 2370Sstevel@tonic-gate gss_name_t internal_name = GSS_C_NO_NAME; 2380Sstevel@tonic-gate gss_name_t allocated_name = GSS_C_NO_NAME; 2390Sstevel@tonic-gate gss_cred_id_t cred = NULL; 2400Sstevel@tonic-gate gss_OID new_mechs_array = NULL; 2410Sstevel@tonic-gate gss_cred_id_t *new_cred_array = NULL; 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate /* check input parameters */ 2440Sstevel@tonic-gate if (minor_status == NULL) 2450Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 2460Sstevel@tonic-gate *minor_status = 0; 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate if (input_cred_handle == GSS_C_NO_CREDENTIAL && 2490Sstevel@tonic-gate output_cred_handle == NULL) 2500Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate if (output_cred_handle) 2530Sstevel@tonic-gate *output_cred_handle = GSS_C_NO_CREDENTIAL; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate if (actual_mechs) 2560Sstevel@tonic-gate *actual_mechs = NULL; 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate if (acceptor_time_rec) 2590Sstevel@tonic-gate *acceptor_time_rec = 0; 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate if (initiator_time_rec) 2620Sstevel@tonic-gate *initiator_time_rec = 0; 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate mech = __gss_get_mechanism(desired_mech); 2650Sstevel@tonic-gate if (!mech) 2660Sstevel@tonic-gate return (GSS_S_BAD_MECH); 2670Sstevel@tonic-gate else if (!mech->gss_acquire_cred) 2680Sstevel@tonic-gate return (GSS_S_UNAVAILABLE); 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate if (input_cred_handle == GSS_C_NO_CREDENTIAL) { 2710Sstevel@tonic-gate union_cred = malloc(sizeof (gss_union_cred_desc)); 2720Sstevel@tonic-gate if (union_cred == NULL) 2730Sstevel@tonic-gate return (GSS_S_FAILURE); 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate (void) memset(union_cred, 0, sizeof (gss_union_cred_desc)); 276160Swyllys } else { 277160Swyllys /* Input Cred is non-NULL */ 278160Swyllys union_cred = (gss_union_cred_t)input_cred_handle; 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate if (__gss_get_mechanism_cred(union_cred, desired_mech) != 281160Swyllys GSS_C_NO_CREDENTIAL) { 282160Swyllys status = GSS_S_DUPLICATE_ELEMENT; 283160Swyllys goto errout; 284160Swyllys } 2850Sstevel@tonic-gate 286160Swyllys /* 287160Swyllys * If no name was given, determine the name from the 288160Swyllys * existing credential. 289160Swyllys */ 290160Swyllys if (desired_name == GSS_C_NO_NAME) { 291160Swyllys if (gss_import_name(minor_status, 292160Swyllys &union_cred->auxinfo.name, 293160Swyllys union_cred->auxinfo.name_type, 294160Swyllys &allocated_name) == GSS_S_COMPLETE && 295160Swyllys (gss_canonicalize_name(minor_status, 296160Swyllys allocated_name, 297160Swyllys &mech->mech_type, 298160Swyllys NULL) == GSS_S_COMPLETE)) { 2990Sstevel@tonic-gate internal_name = allocated_name; 3000Sstevel@tonic-gate } 301160Swyllys } /* else, get the name from the desired_name below */ 302160Swyllys } 303160Swyllys if (desired_name != GSS_C_NO_NAME) { 304160Swyllys /* may need to create a mechanism specific name */ 305160Swyllys union_name = (gss_union_name_t)desired_name; 306160Swyllys 307160Swyllys if (union_name->mech_type && 308160Swyllys g_OID_equal(union_name->mech_type, 309160Swyllys &mech->mech_type)) 310160Swyllys internal_name = union_name->mech_name; 311160Swyllys else { 312160Swyllys if (__gss_import_internal_name(minor_status, 313160Swyllys &mech->mech_type, union_name, 314160Swyllys &allocated_name) != GSS_S_COMPLETE) { 315160Swyllys status = GSS_S_BAD_NAME; 316160Swyllys goto errout; 317160Swyllys } 318160Swyllys internal_name = allocated_name; 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT) 3230Sstevel@tonic-gate time_req = acceptor_time_req; 3240Sstevel@tonic-gate else if (cred_usage == GSS_C_INITIATE) 3250Sstevel@tonic-gate time_req = initiator_time_req; 3260Sstevel@tonic-gate else if (cred_usage == GSS_C_BOTH) 3270Sstevel@tonic-gate time_req = (acceptor_time_req > initiator_time_req) ? 3280Sstevel@tonic-gate acceptor_time_req : initiator_time_req; 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate status = mech->gss_acquire_cred(mech->context, minor_status, 3310Sstevel@tonic-gate internal_name, time_req, 3320Sstevel@tonic-gate GSS_C_NULL_OID_SET, cred_usage, 3330Sstevel@tonic-gate &cred, NULL, &time_rec); 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate if (status != GSS_S_COMPLETE) 3360Sstevel@tonic-gate goto errout; 3370Sstevel@tonic-gate 338160Swyllys /* may need to set credential auxinfo structure */ 3390Sstevel@tonic-gate if (union_cred->auxinfo.creation_time == 0) { 3400Sstevel@tonic-gate union_cred->auxinfo.creation_time = time(NULL); 3410Sstevel@tonic-gate union_cred->auxinfo.time_rec = time_rec; 3420Sstevel@tonic-gate union_cred->auxinfo.cred_usage = cred_usage; 3430Sstevel@tonic-gate 3443376Smp153739 /* 3453376Smp153739 * If internal_name is GSS_C_NO_NAME a cred with no associated 3463376Smp153739 * name was requested: don't set auxinfo.name or auxinfo.name_type. 3473376Smp153739 */ 3483376Smp153739 if (internal_name != GSS_C_NO_NAME) { 3493376Smp153739 if ((status = mech->gss_display_name(mech->context, 3503376Smp153739 &temp_minor_status, internal_name, 3513376Smp153739 &union_cred->auxinfo.name, 3523376Smp153739 &union_cred->auxinfo.name_type)) != 3533376Smp153739 GSS_S_COMPLETE) 3540Sstevel@tonic-gate goto errout; 3550Sstevel@tonic-gate } 3560Sstevel@tonic-gate } 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate /* now add the new credential elements */ 3590Sstevel@tonic-gate new_mechs_array = (gss_OID) 3600Sstevel@tonic-gate malloc(sizeof (gss_OID_desc) * (union_cred->count+1)); 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate new_cred_array = (gss_cred_id_t *) 3630Sstevel@tonic-gate malloc(sizeof (gss_cred_id_t) * (union_cred->count+1)); 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate if (!new_mechs_array || !new_cred_array) { 3660Sstevel@tonic-gate status = GSS_S_FAILURE; 3670Sstevel@tonic-gate goto errout; 3680Sstevel@tonic-gate } 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate if (acceptor_time_rec) 3710Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) 3720Sstevel@tonic-gate *acceptor_time_rec = time_rec; 3730Sstevel@tonic-gate if (initiator_time_rec) 3740Sstevel@tonic-gate if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) 3750Sstevel@tonic-gate *initiator_time_rec = time_rec; 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* 3780Sstevel@tonic-gate * OK, expand the mechanism array and the credential array 3790Sstevel@tonic-gate */ 3800Sstevel@tonic-gate (void) memcpy(new_mechs_array, union_cred->mechs_array, 3810Sstevel@tonic-gate sizeof (gss_OID_desc) * union_cred->count); 3820Sstevel@tonic-gate (void) memcpy(new_cred_array, union_cred->cred_array, 3830Sstevel@tonic-gate sizeof (gss_cred_id_t) * union_cred->count); 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate new_cred_array[union_cred->count] = cred; 3860Sstevel@tonic-gate if ((new_mechs_array[union_cred->count].elements = 3870Sstevel@tonic-gate malloc(mech->mech_type.length)) == NULL) 3880Sstevel@tonic-gate goto errout; 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate g_OID_copy(&new_mechs_array[union_cred->count], 3910Sstevel@tonic-gate &mech->mech_type); 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate if (actual_mechs) { 3940Sstevel@tonic-gate *actual_mechs = create_actual_mechs(new_mechs_array, 3950Sstevel@tonic-gate union_cred->count + 1); 3960Sstevel@tonic-gate if (*actual_mechs == NULL) { 3970Sstevel@tonic-gate free(new_mechs_array[union_cred->count].elements); 3980Sstevel@tonic-gate goto errout; 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate if (output_cred_handle == NULL) { 4030Sstevel@tonic-gate free(union_cred->mechs_array); 4040Sstevel@tonic-gate free(union_cred->cred_array); 4050Sstevel@tonic-gate new_union_cred = union_cred; 4060Sstevel@tonic-gate } else { 4070Sstevel@tonic-gate new_union_cred = malloc(sizeof (gss_union_cred_desc)); 4080Sstevel@tonic-gate if (new_union_cred == NULL) { 4090Sstevel@tonic-gate free(new_mechs_array[union_cred->count].elements); 4100Sstevel@tonic-gate goto errout; 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate *new_union_cred = *union_cred; 4130Sstevel@tonic-gate *output_cred_handle = (gss_cred_id_t)new_union_cred; 4140Sstevel@tonic-gate } 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate new_union_cred->mechs_array = new_mechs_array; 4170Sstevel@tonic-gate new_union_cred->cred_array = new_cred_array; 4180Sstevel@tonic-gate new_union_cred->count++; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate /* We're done with the internal name. Free it if we allocated it. */ 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate if (allocated_name) 4230Sstevel@tonic-gate (void) __gss_release_internal_name(&temp_minor_status, 4240Sstevel@tonic-gate &mech->mech_type, 4250Sstevel@tonic-gate &allocated_name); 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate return (GSS_S_COMPLETE); 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate errout: 4300Sstevel@tonic-gate if (new_mechs_array) 4310Sstevel@tonic-gate free(new_mechs_array); 4320Sstevel@tonic-gate if (new_cred_array) 4330Sstevel@tonic-gate free(new_cred_array); 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate if (cred != NULL && mech->gss_release_cred) 4360Sstevel@tonic-gate mech->gss_release_cred(mech->context, 4370Sstevel@tonic-gate &temp_minor_status, &cred); 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate if (allocated_name) 4400Sstevel@tonic-gate (void) __gss_release_internal_name(&temp_minor_status, 4410Sstevel@tonic-gate &mech->mech_type, 4420Sstevel@tonic-gate &allocated_name); 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) { 4450Sstevel@tonic-gate if (union_cred->auxinfo.name.value) 4460Sstevel@tonic-gate free(union_cred->auxinfo.name.value); 4470Sstevel@tonic-gate free(union_cred); 4480Sstevel@tonic-gate } 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate return (status); 4510Sstevel@tonic-gate } 452