1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * glue routine for gss_acquire_cred 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <mechglueP.h> 34*0Sstevel@tonic-gate #include <stdio.h> 35*0Sstevel@tonic-gate #ifdef HAVE_STDLIB_H 36*0Sstevel@tonic-gate #include <stdlib.h> 37*0Sstevel@tonic-gate #endif 38*0Sstevel@tonic-gate #include <string.h> 39*0Sstevel@tonic-gate #include <errno.h> 40*0Sstevel@tonic-gate #include <time.h> 41*0Sstevel@tonic-gate /* local functions */ 42*0Sstevel@tonic-gate static gss_OID_set create_actual_mechs(const gss_OID, int); 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate static gss_OID_set 45*0Sstevel@tonic-gate create_actual_mechs(mechs_array, count) 46*0Sstevel@tonic-gate const gss_OID mechs_array; 47*0Sstevel@tonic-gate int count; 48*0Sstevel@tonic-gate { 49*0Sstevel@tonic-gate gss_OID_set actual_mechs; 50*0Sstevel@tonic-gate int i; 51*0Sstevel@tonic-gate OM_uint32 minor; 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate actual_mechs = (gss_OID_set) malloc(sizeof (gss_OID_set_desc)); 54*0Sstevel@tonic-gate if (!actual_mechs) 55*0Sstevel@tonic-gate return (NULL); 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate actual_mechs->elements = (gss_OID) 58*0Sstevel@tonic-gate malloc(sizeof (gss_OID_desc) * count); 59*0Sstevel@tonic-gate if (!actual_mechs->elements) { 60*0Sstevel@tonic-gate free(actual_mechs); 61*0Sstevel@tonic-gate return (NULL); 62*0Sstevel@tonic-gate } 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate actual_mechs->count = 0; 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate for (i = 0; i < count; i++) { 67*0Sstevel@tonic-gate actual_mechs->elements[i].elements = (void *) 68*0Sstevel@tonic-gate malloc(mechs_array[i].length); 69*0Sstevel@tonic-gate if (actual_mechs->elements[i].elements == NULL) { 70*0Sstevel@tonic-gate (void) gss_release_oid_set(&minor, &actual_mechs); 71*0Sstevel@tonic-gate return (NULL); 72*0Sstevel@tonic-gate } 73*0Sstevel@tonic-gate g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]); 74*0Sstevel@tonic-gate actual_mechs->count++; 75*0Sstevel@tonic-gate } 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate return (actual_mechs); 78*0Sstevel@tonic-gate } 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate OM_uint32 82*0Sstevel@tonic-gate gss_acquire_cred(minor_status, 83*0Sstevel@tonic-gate desired_name, 84*0Sstevel@tonic-gate time_req, 85*0Sstevel@tonic-gate desired_mechs, 86*0Sstevel@tonic-gate cred_usage, 87*0Sstevel@tonic-gate output_cred_handle, 88*0Sstevel@tonic-gate actual_mechs, 89*0Sstevel@tonic-gate time_rec) 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate OM_uint32 * minor_status; 92*0Sstevel@tonic-gate const gss_name_t desired_name; 93*0Sstevel@tonic-gate OM_uint32 time_req; 94*0Sstevel@tonic-gate const gss_OID_set desired_mechs; 95*0Sstevel@tonic-gate int cred_usage; 96*0Sstevel@tonic-gate gss_cred_id_t *output_cred_handle; 97*0Sstevel@tonic-gate gss_OID_set * actual_mechs; 98*0Sstevel@tonic-gate OM_uint32 * time_rec; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate { 101*0Sstevel@tonic-gate OM_uint32 major = GSS_S_FAILURE; 102*0Sstevel@tonic-gate OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE; 103*0Sstevel@tonic-gate gss_OID_set_desc default_OID_set; 104*0Sstevel@tonic-gate gss_OID_set mechs; 105*0Sstevel@tonic-gate gss_OID_desc default_OID; 106*0Sstevel@tonic-gate gss_mechanism mech; 107*0Sstevel@tonic-gate int i; 108*0Sstevel@tonic-gate gss_union_cred_t creds; 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* start by checking parameters */ 111*0Sstevel@tonic-gate if (!minor_status) 112*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 113*0Sstevel@tonic-gate *minor_status = 0; 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate if (!output_cred_handle) 116*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate *output_cred_handle = GSS_C_NO_CREDENTIAL; 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* Set output parameters to NULL for now */ 121*0Sstevel@tonic-gate if (actual_mechs) 122*0Sstevel@tonic-gate *actual_mechs = GSS_C_NULL_OID_SET; 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate if (time_rec) 125*0Sstevel@tonic-gate *time_rec = 0; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate /* 128*0Sstevel@tonic-gate * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an 129*0Sstevel@tonic-gate * appropriate default. We use the first mechanism in the 130*0Sstevel@tonic-gate * mechansim list as the default. This set is created with 131*0Sstevel@tonic-gate * statics thus needs not be freed 132*0Sstevel@tonic-gate */ 133*0Sstevel@tonic-gate if (desired_mechs == GSS_C_NULL_OID_SET) { 134*0Sstevel@tonic-gate mech = __gss_get_mechanism(NULL); 135*0Sstevel@tonic-gate if (mech == NULL) 136*0Sstevel@tonic-gate return (GSS_S_BAD_MECH); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate mechs = &default_OID_set; 139*0Sstevel@tonic-gate default_OID_set.count = 1; 140*0Sstevel@tonic-gate default_OID_set.elements = &default_OID; 141*0Sstevel@tonic-gate default_OID.length = mech->mech_type.length; 142*0Sstevel@tonic-gate default_OID.elements = mech->mech_type.elements; 143*0Sstevel@tonic-gate } else 144*0Sstevel@tonic-gate mechs = desired_mechs; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate if (mechs->count == NULL) 147*0Sstevel@tonic-gate return (GSS_S_BAD_MECH); 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate /* allocate the output credential structure */ 150*0Sstevel@tonic-gate creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc)); 151*0Sstevel@tonic-gate if (creds == NULL) 152*0Sstevel@tonic-gate return (GSS_S_FAILURE); 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate /* initialize to 0s */ 155*0Sstevel@tonic-gate (void) memset(creds, 0, sizeof (gss_union_cred_desc)); 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate /* for each requested mech attempt to obtain a credential */ 158*0Sstevel@tonic-gate for (i = 0; i < mechs->count; i++) { 159*0Sstevel@tonic-gate major = gss_add_cred(minor_status, (gss_cred_id_t)creds, 160*0Sstevel@tonic-gate desired_name, 161*0Sstevel@tonic-gate &mechs->elements[i], 162*0Sstevel@tonic-gate cred_usage, time_req, time_req, NULL, 163*0Sstevel@tonic-gate NULL, &initTimeOut, &acceptTimeOut); 164*0Sstevel@tonic-gate if (major == GSS_S_COMPLETE) { 165*0Sstevel@tonic-gate /* update the credential's time */ 166*0Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT) { 167*0Sstevel@tonic-gate if (outTime > acceptTimeOut) 168*0Sstevel@tonic-gate outTime = acceptTimeOut; 169*0Sstevel@tonic-gate } else if (cred_usage == GSS_C_INITIATE) { 170*0Sstevel@tonic-gate if (outTime > initTimeOut) 171*0Sstevel@tonic-gate outTime = initTimeOut; 172*0Sstevel@tonic-gate } else { 173*0Sstevel@tonic-gate /* 174*0Sstevel@tonic-gate * time_rec is the lesser of the 175*0Sstevel@tonic-gate * init/accept times 176*0Sstevel@tonic-gate */ 177*0Sstevel@tonic-gate if (initTimeOut > acceptTimeOut) 178*0Sstevel@tonic-gate outTime = (outTime > acceptTimeOut) ? 179*0Sstevel@tonic-gate acceptTimeOut : outTime; 180*0Sstevel@tonic-gate else 181*0Sstevel@tonic-gate outTime = (outTime > initTimeOut) ? 182*0Sstevel@tonic-gate initTimeOut : outTime; 183*0Sstevel@tonic-gate } 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate } /* for */ 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate /* ensure that we have at least one credential element */ 188*0Sstevel@tonic-gate if (creds->count < 1) { 189*0Sstevel@tonic-gate free(creds); 190*0Sstevel@tonic-gate return (major); 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate /* 194*0Sstevel@tonic-gate * fill in output parameters 195*0Sstevel@tonic-gate * setup the actual mechs output parameter 196*0Sstevel@tonic-gate */ 197*0Sstevel@tonic-gate if (actual_mechs != NULL) { 198*0Sstevel@tonic-gate if ((*actual_mechs = create_actual_mechs(creds->mechs_array, 199*0Sstevel@tonic-gate creds->count)) == NULL) { 200*0Sstevel@tonic-gate (void) gss_release_cred(minor_status, 201*0Sstevel@tonic-gate (gss_cred_id_t *)&creds); 202*0Sstevel@tonic-gate *minor_status = 0; 203*0Sstevel@tonic-gate return (GSS_S_FAILURE); 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate if (time_rec) 208*0Sstevel@tonic-gate *time_rec = outTime; 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate *output_cred_handle = (gss_cred_id_t)creds; 212*0Sstevel@tonic-gate return (GSS_S_COMPLETE); 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate /* V2 INTERFACE */ 216*0Sstevel@tonic-gate OM_uint32 217*0Sstevel@tonic-gate gss_add_cred(minor_status, input_cred_handle, 218*0Sstevel@tonic-gate desired_name, desired_mech, cred_usage, 219*0Sstevel@tonic-gate initiator_time_req, acceptor_time_req, 220*0Sstevel@tonic-gate output_cred_handle, actual_mechs, 221*0Sstevel@tonic-gate initiator_time_rec, acceptor_time_rec) 222*0Sstevel@tonic-gate OM_uint32 *minor_status; 223*0Sstevel@tonic-gate const gss_cred_id_t input_cred_handle; 224*0Sstevel@tonic-gate const gss_name_t desired_name; 225*0Sstevel@tonic-gate const gss_OID desired_mech; 226*0Sstevel@tonic-gate gss_cred_usage_t cred_usage; 227*0Sstevel@tonic-gate OM_uint32 initiator_time_req; 228*0Sstevel@tonic-gate OM_uint32 acceptor_time_req; 229*0Sstevel@tonic-gate gss_cred_id_t *output_cred_handle; 230*0Sstevel@tonic-gate gss_OID_set *actual_mechs; 231*0Sstevel@tonic-gate OM_uint32 *initiator_time_rec; 232*0Sstevel@tonic-gate OM_uint32 *acceptor_time_rec; 233*0Sstevel@tonic-gate { 234*0Sstevel@tonic-gate OM_uint32 status, time_req, time_rec, temp_minor_status; 235*0Sstevel@tonic-gate gss_mechanism mech; 236*0Sstevel@tonic-gate gss_union_name_t union_name = NULL; 237*0Sstevel@tonic-gate gss_union_cred_t union_cred, new_union_cred; 238*0Sstevel@tonic-gate gss_name_t internal_name = GSS_C_NO_NAME; 239*0Sstevel@tonic-gate gss_name_t allocated_name = GSS_C_NO_NAME; 240*0Sstevel@tonic-gate gss_cred_id_t cred = NULL; 241*0Sstevel@tonic-gate gss_OID new_mechs_array = NULL; 242*0Sstevel@tonic-gate gss_cred_id_t *new_cred_array = NULL; 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate /* check input parameters */ 245*0Sstevel@tonic-gate if (minor_status == NULL) 246*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 247*0Sstevel@tonic-gate *minor_status = 0; 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate if (input_cred_handle == GSS_C_NO_CREDENTIAL && 250*0Sstevel@tonic-gate output_cred_handle == NULL) 251*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate if (output_cred_handle) 254*0Sstevel@tonic-gate *output_cred_handle = GSS_C_NO_CREDENTIAL; 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate if (actual_mechs) 257*0Sstevel@tonic-gate *actual_mechs = NULL; 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate if (acceptor_time_rec) 260*0Sstevel@tonic-gate *acceptor_time_rec = 0; 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate if (initiator_time_rec) 263*0Sstevel@tonic-gate *initiator_time_rec = 0; 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate mech = __gss_get_mechanism(desired_mech); 266*0Sstevel@tonic-gate if (!mech) 267*0Sstevel@tonic-gate return (GSS_S_BAD_MECH); 268*0Sstevel@tonic-gate else if (!mech->gss_acquire_cred) 269*0Sstevel@tonic-gate return (GSS_S_UNAVAILABLE); 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate if (input_cred_handle == GSS_C_NO_CREDENTIAL) { 272*0Sstevel@tonic-gate union_cred = malloc(sizeof (gss_union_cred_desc)); 273*0Sstevel@tonic-gate if (union_cred == NULL) 274*0Sstevel@tonic-gate return (GSS_S_FAILURE); 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate (void) memset(union_cred, 0, sizeof (gss_union_cred_desc)); 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate /* for default credentials we will use GSS_C_NO_NAME */ 279*0Sstevel@tonic-gate internal_name = GSS_C_NO_NAME; 280*0Sstevel@tonic-gate } else { 281*0Sstevel@tonic-gate union_cred = (gss_union_cred_t)input_cred_handle; 282*0Sstevel@tonic-gate if (__gss_get_mechanism_cred(union_cred, desired_mech) != 283*0Sstevel@tonic-gate GSS_C_NO_CREDENTIAL) 284*0Sstevel@tonic-gate return (GSS_S_DUPLICATE_ELEMENT); 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate /* may need to create a mechanism specific name */ 287*0Sstevel@tonic-gate if (desired_name) { 288*0Sstevel@tonic-gate union_name = (gss_union_name_t)desired_name; 289*0Sstevel@tonic-gate if (union_name->mech_type && 290*0Sstevel@tonic-gate g_OID_equal(union_name->mech_type, 291*0Sstevel@tonic-gate &mech->mech_type)) 292*0Sstevel@tonic-gate internal_name = union_name->mech_name; 293*0Sstevel@tonic-gate else { 294*0Sstevel@tonic-gate if (__gss_import_internal_name(minor_status, 295*0Sstevel@tonic-gate &mech->mech_type, union_name, 296*0Sstevel@tonic-gate &allocated_name) != GSS_S_COMPLETE) 297*0Sstevel@tonic-gate return (GSS_S_BAD_NAME); 298*0Sstevel@tonic-gate internal_name = allocated_name; 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT) 305*0Sstevel@tonic-gate time_req = acceptor_time_req; 306*0Sstevel@tonic-gate else if (cred_usage == GSS_C_INITIATE) 307*0Sstevel@tonic-gate time_req = initiator_time_req; 308*0Sstevel@tonic-gate else if (cred_usage == GSS_C_BOTH) 309*0Sstevel@tonic-gate time_req = (acceptor_time_req > initiator_time_req) ? 310*0Sstevel@tonic-gate acceptor_time_req : initiator_time_req; 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate status = mech->gss_acquire_cred(mech->context, minor_status, 313*0Sstevel@tonic-gate internal_name, time_req, 314*0Sstevel@tonic-gate GSS_C_NULL_OID_SET, cred_usage, 315*0Sstevel@tonic-gate &cred, NULL, &time_rec); 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate if (status != GSS_S_COMPLETE) 318*0Sstevel@tonic-gate goto errout; 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate /* may need to set credential auxinfo strucutre */ 321*0Sstevel@tonic-gate if (union_cred->auxinfo.creation_time == 0) { 322*0Sstevel@tonic-gate union_cred->auxinfo.creation_time = time(NULL); 323*0Sstevel@tonic-gate union_cred->auxinfo.time_rec = time_rec; 324*0Sstevel@tonic-gate union_cred->auxinfo.cred_usage = cred_usage; 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate /* 327*0Sstevel@tonic-gate * we must set the name; if name is not supplied 328*0Sstevel@tonic-gate * we must do inquire cred to get it 329*0Sstevel@tonic-gate */ 330*0Sstevel@tonic-gate if (internal_name == NULL) { 331*0Sstevel@tonic-gate if (mech->gss_inquire_cred == NULL || 332*0Sstevel@tonic-gate ((status = mech->gss_inquire_cred( 333*0Sstevel@tonic-gate mech->context, 334*0Sstevel@tonic-gate &temp_minor_status, cred, 335*0Sstevel@tonic-gate &allocated_name, NULL, NULL, 336*0Sstevel@tonic-gate NULL)) != GSS_S_COMPLETE)) 337*0Sstevel@tonic-gate goto errout; 338*0Sstevel@tonic-gate internal_name = allocated_name; 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate if ((status = mech->gss_display_name(mech->context, 342*0Sstevel@tonic-gate &temp_minor_status, internal_name, 343*0Sstevel@tonic-gate &union_cred->auxinfo.name, 344*0Sstevel@tonic-gate &union_cred->auxinfo.name_type)) != 345*0Sstevel@tonic-gate GSS_S_COMPLETE) 346*0Sstevel@tonic-gate goto errout; 347*0Sstevel@tonic-gate } 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate /* now add the new credential elements */ 350*0Sstevel@tonic-gate new_mechs_array = (gss_OID) 351*0Sstevel@tonic-gate malloc(sizeof (gss_OID_desc) * (union_cred->count+1)); 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate new_cred_array = (gss_cred_id_t *) 354*0Sstevel@tonic-gate malloc(sizeof (gss_cred_id_t) * (union_cred->count+1)); 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate if (!new_mechs_array || !new_cred_array) { 357*0Sstevel@tonic-gate status = GSS_S_FAILURE; 358*0Sstevel@tonic-gate goto errout; 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate if (acceptor_time_rec) 362*0Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) 363*0Sstevel@tonic-gate *acceptor_time_rec = time_rec; 364*0Sstevel@tonic-gate if (initiator_time_rec) 365*0Sstevel@tonic-gate if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) 366*0Sstevel@tonic-gate *initiator_time_rec = time_rec; 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate /* 369*0Sstevel@tonic-gate * OK, expand the mechanism array and the credential array 370*0Sstevel@tonic-gate */ 371*0Sstevel@tonic-gate (void) memcpy(new_mechs_array, union_cred->mechs_array, 372*0Sstevel@tonic-gate sizeof (gss_OID_desc) * union_cred->count); 373*0Sstevel@tonic-gate (void) memcpy(new_cred_array, union_cred->cred_array, 374*0Sstevel@tonic-gate sizeof (gss_cred_id_t) * union_cred->count); 375*0Sstevel@tonic-gate 376*0Sstevel@tonic-gate new_cred_array[union_cred->count] = cred; 377*0Sstevel@tonic-gate if ((new_mechs_array[union_cred->count].elements = 378*0Sstevel@tonic-gate malloc(mech->mech_type.length)) == NULL) 379*0Sstevel@tonic-gate goto errout; 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate g_OID_copy(&new_mechs_array[union_cred->count], 382*0Sstevel@tonic-gate &mech->mech_type); 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate if (actual_mechs) { 385*0Sstevel@tonic-gate *actual_mechs = create_actual_mechs(new_mechs_array, 386*0Sstevel@tonic-gate union_cred->count + 1); 387*0Sstevel@tonic-gate if (*actual_mechs == NULL) { 388*0Sstevel@tonic-gate free(new_mechs_array[union_cred->count].elements); 389*0Sstevel@tonic-gate goto errout; 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate } 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate if (output_cred_handle == NULL) { 394*0Sstevel@tonic-gate free(union_cred->mechs_array); 395*0Sstevel@tonic-gate free(union_cred->cred_array); 396*0Sstevel@tonic-gate new_union_cred = union_cred; 397*0Sstevel@tonic-gate } else { 398*0Sstevel@tonic-gate new_union_cred = malloc(sizeof (gss_union_cred_desc)); 399*0Sstevel@tonic-gate if (new_union_cred == NULL) { 400*0Sstevel@tonic-gate free(new_mechs_array[union_cred->count].elements); 401*0Sstevel@tonic-gate goto errout; 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate *new_union_cred = *union_cred; 404*0Sstevel@tonic-gate *output_cred_handle = (gss_cred_id_t)new_union_cred; 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate new_union_cred->mechs_array = new_mechs_array; 408*0Sstevel@tonic-gate new_union_cred->cred_array = new_cred_array; 409*0Sstevel@tonic-gate new_union_cred->count++; 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gate /* We're done with the internal name. Free it if we allocated it. */ 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate if (allocated_name) 414*0Sstevel@tonic-gate (void) __gss_release_internal_name(&temp_minor_status, 415*0Sstevel@tonic-gate &mech->mech_type, 416*0Sstevel@tonic-gate &allocated_name); 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate return (GSS_S_COMPLETE); 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate errout: 421*0Sstevel@tonic-gate if (new_mechs_array) 422*0Sstevel@tonic-gate free(new_mechs_array); 423*0Sstevel@tonic-gate if (new_cred_array) 424*0Sstevel@tonic-gate free(new_cred_array); 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate if (cred != NULL && mech->gss_release_cred) 427*0Sstevel@tonic-gate mech->gss_release_cred(mech->context, 428*0Sstevel@tonic-gate &temp_minor_status, &cred); 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate if (allocated_name) 431*0Sstevel@tonic-gate (void) __gss_release_internal_name(&temp_minor_status, 432*0Sstevel@tonic-gate &mech->mech_type, 433*0Sstevel@tonic-gate &allocated_name); 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) { 436*0Sstevel@tonic-gate if (union_cred->auxinfo.name.value) 437*0Sstevel@tonic-gate free(union_cred->auxinfo.name.value); 438*0Sstevel@tonic-gate free(union_cred); 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate return (status); 442*0Sstevel@tonic-gate } 443