1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 | #pragma ident "@(#)g_acquire_cred.c 1.23 04/09/08 SMI" 6 | #pragma ident "@(#)g_acquire_cred.c 1.22 04/02/23 SMI" 7 8 /* 9 * glue routine for gss_acquire_cred 10 */ 11 12 #include <mechglueP.h> 13 #include <stdio.h> 14 #ifdef HAVE_STDLIB_H 15 #include <stdlib.h> 16 #endif 17 #include <string.h> 18 #include <errno.h> 19 #include <time.h> 20 /* local functions */ 21 static gss_OID_set create_actual_mechs(const gss_OID, int); 22 23 static gss_OID_set 24 | create_actual_mechs(creds) 25 | gss_union_cred_t creds; 24 | create_actual_mechs(mechs_array, count) 25 | const gss_OID mechs_array; 26 + int count; 27 { 28 gss_OID_set actual_mechs; 29 int i; 30 + OM_uint32 minor; 31 32 actual_mechs = (gss_OID_set) malloc(sizeof (gss_OID_set_desc)); 33 if (!actual_mechs) 34 return (NULL); 35 36 actual_mechs->elements = (gss_OID) 35 | malloc(sizeof (gss_OID_desc) * creds->count); 37 | malloc(sizeof (gss_OID_desc) * count); 38 if (!actual_mechs->elements) { 39 free(actual_mechs); 40 return (NULL); 41 } 42 43 actual_mechs->count = 0; 44 43 | for (i = 0; i < creds->count; i++) { 45 | for (i = 0; i < count; i++) { 44 - actual_mechs->elements[i].elements = 45 - creds->mechs_array[i].length; 46 actual_mechs->elements[i].elements = (void *) 47 | malloc(creds->mechs_array[i].length); 48 | memcpy(actual_mechs->elements[i].elements, 49 | creds->mechs_array[i].elements, 50 | creds->mechs_array[i].length); 47 | malloc(mechs_array[i].length); 48 | if (actual_mechs->elements[i].elements == NULL) { 49 | (void) gss_release_oid_set(&minor, &actual_mechs); 50 | return (NULL); 51 } 52 + g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]); 53 + actual_mechs->count++; 54 + } 55 56 return (actual_mechs); 57 } 58 59 60 OM_uint32 61 gss_acquire_cred(minor_status, 62 desired_name, 63 time_req, 64 desired_mechs, 65 cred_usage, 66 output_cred_handle, 67 actual_mechs, 68 time_rec) 69 70 OM_uint32 * minor_status; 71 const gss_name_t desired_name; 72 OM_uint32 time_req; 73 const gss_OID_set desired_mechs; 74 int cred_usage; 75 gss_cred_id_t *output_cred_handle; 76 gss_OID_set * actual_mechs; 77 OM_uint32 * time_rec; 78 79 { 77 | OM_uint32 status, temp_minor_status, temp_time_rec = ~0; 78 | unsigned int i, j, creds_acquired = 0; 80 | OM_uint32 major = GSS_S_FAILURE; 81 | OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE; 79 - int k; 80 - gss_union_name_t union_name; 81 - gss_name_t internal_name; 82 - gss_union_cred_t creds; 82 gss_OID_set_desc default_OID_set; 83 + gss_OID_set mechs; 85 - gss_OID specific_mech_type = 0; 84 gss_OID_desc default_OID; 85 gss_mechanism mech; 86 + int i; 87 + gss_union_cred_t creds; 88 88 | /* 89 | * This struct is used to keep track of which mech_types are 90 | * actually available and to store the credentials returned 91 | * from them by each mechanism specific gss_acquire_cred() call. 89 | /* start by checking parameters */ 90 | if (!minor_status) 91 | return (GSS_S_CALL_INACCESSIBLE_WRITE); 92 | *minor_status = 0; 92 - * The results are used to construct the final union_cred 93 - * structure returned by the glue layer gss_acquire_cred() call 94 - * and the actual_mechs gss_OID_set returned. 95 - */ 93 97 | struct creds_returned { 98 | unsigned char available; 94 | if (!output_cred_handle) 95 | return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); 99 - gss_cred_id_t cred; 100 - } *creds_returned; 96 102 | gss_initialize(); 97 | *output_cred_handle = GSS_C_NO_CREDENTIAL; 98 104 | /* Set this to NULL for now */ 99 | /* Set output parameters to NULL for now */ 105 - 100 if (actual_mechs) 101 *actual_mechs = GSS_C_NULL_OID_SET; 102 109 | if (minor_status) 110 | *minor_status = 0; 103 | if (time_rec) 104 | *time_rec = 0; 112 - /* No need to continue if we don't have a place to store the creds */ 113 - if (output_cred_handle == NULL) 114 - return GSS_S_COMPLETE; 115 - 105 106 /* 107 * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an 118 | * appropriate default. 108 | * appropriate default. We use the first mechanism in the 109 + * mechansim list as the default. This set is created with 110 + * statics thus needs not be freed 111 */ 112 if (desired_mechs == GSS_C_NULL_OID_SET) { 121 | /* 113 | mech = __gss_get_mechanism(NULL); 122 - * If union_name->mech_type is NULL then we get the default 123 - * mechanism; otherwise, we get the mechanism for the 124 - * mechanism-specific name. 125 - */ 126 - mech = __gss_get_mechanism(specific_mech_type); 114 if (mech == NULL) 115 return (GSS_S_BAD_MECH); 129 | desired_mechs = &default_OID_set; 116 | 117 + mechs = &default_OID_set; 118 default_OID_set.count = 1; 119 default_OID_set.elements = &default_OID; 120 default_OID.length = mech->mech_type.length; 134 - } 135 - 136 - /* 137 - * Now allocate the creds returned array. There is one element 138 - * for each member of the desired_mechs argument. 139 - */ 140 - 141 - creds_returned = (struct creds_returned *) 142 - malloc(sizeof(struct creds_returned) * desired_mechs->count); 143 - 144 - /* 145 - * For each requested mechanism in desired_mechs, determine if it 146 - * is supported. If so, mark the corresponding element in 147 - * creds_returned->available as 1 and call the mechanism 148 - * specific gss_acquire_cred(), placing the returned cred in 149 - * creds_returned->cred. If not, mark creds_returned->available as 150 - * 0. 151 - */ 152 - status = GSS_S_BAD_MECH; 153 - for (j=0; j < desired_mechs->count; j++) { 154 - creds_returned[j].available = 0; 155 - 156 - mech = __gss_get_mechanism (&desired_mechs->elements[j]); 157 - if (!mech || !mech->gss_acquire_cred) 158 - continue; 159 - /* 160 - * If this is a mechanism-specific name, then only use the 161 - * mechanism of the name. 162 - */ 163 - if (specific_mech_type && !g_OID_equal(specific_mech_type, 164 - &mech->mech_type)) 165 - continue; 166 - /* 167 - * If this is not a mechanism-specific name, then we need to 168 - * do an import the external name in union_name first. 169 - */ 170 - if (union_name == 0) 171 - internal_name = (gss_name_t) 0; 172 - else if (!union_name->mech_type) { 173 - if (__gss_import_internal_name(&temp_minor_status, 174 - &mech->mech_type, 175 - union_name, &internal_name)) { 176 - continue; 177 - } 121 default_OID.elements = mech->mech_type.elements; 122 } else 179 | internal_name = union_name->mech_name; 123 | mechs = desired_mechs; 124 181 | status = mech->gss_acquire_cred(mech->context, minor_status, 182 | internal_name, time_req, 125 | if (mechs->count == NULL) 126 | return (GSS_S_BAD_MECH); 183 - desired_mechs, cred_usage, 184 - &creds_returned[j].cred, 185 - NULL, &temp_time_rec); 127 187 | /* Release the internal name, if allocated above */ 188 | if (union_name && !union_name->mech_type) { 189 | (void) __gss_release_internal_name(&temp_minor_status, 190 | &mech->mech_type, 128 | /* allocate the output credential structure */ 129 | creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc)); 130 | if (creds == NULL) 131 | return (GSS_S_FAILURE); 191 - &internal_name); 192 - } 132 194 | if (status != GSS_S_COMPLETE) 195 | continue; 133 | /* initialize to 0s */ 134 | (void) memset(creds, 0, sizeof (gss_union_cred_desc)); 135 136 + /* for each requested mech attempt to obtain a credential */ 137 + for (i = 0; i < mechs->count; i++) { 138 + major = gss_add_cred(minor_status, (gss_cred_id_t)creds, 139 + desired_name, 140 + &mechs->elements[i], 141 + cred_usage, time_req, time_req, NULL, 142 + NULL, &initTimeOut, &acceptTimeOut); 143 + if (major == GSS_S_COMPLETE) { 144 + /* update the credential's time */ 145 + if (cred_usage == GSS_C_ACCEPT) { 146 + if (outTime > acceptTimeOut) 147 + outTime = acceptTimeOut; 148 + } else if (cred_usage == GSS_C_INITIATE) { 149 + if (outTime > initTimeOut) 150 + outTime = initTimeOut; 151 + } else { 152 /* 198 | * Add this into the creds_returned structure, if we got 199 | * a good credential for this mechanism. 153 | * time_rec is the lesser of the 154 | * init/accept times 155 */ 201 | if (time_rec) { 202 | *time_rec = *time_rec > temp_time_rec ? temp_time_rec : *time_rec; 203 | temp_time_rec = *time_rec; 156 | if (initTimeOut > acceptTimeOut) 157 | outTime = (outTime > acceptTimeOut) ? 158 | acceptTimeOut : outTime; 159 + else 160 + outTime = (outTime > initTimeOut) ? 161 + initTimeOut : outTime; 205 - 206 - creds_returned[j].available = 1; 207 - creds_acquired++; 208 - 209 - /* 210 - * If union_name is set, then we're done. Continue, and 211 - * declare success. Otherwise, if do an inquire credentials 212 - * from the first mechanism that succeeds and use that as the 213 - * union name. 214 - */ 215 - if (union_name) 216 - continue; 217 - 218 - status = mech->gss_inquire_cred(mech->context, &temp_minor_status, 219 - creds_returned[j].cred, 220 - &internal_name, 0, 0, 0); 221 - if (status) { 222 - /* Should never happen */ 223 - creds_returned[j].available = 0; 224 - creds_acquired--; 225 - if (mech->gss_release_cred) 226 - mech->gss_release_cred(mech->context, minor_status, 227 - &creds_returned[j].cred); 228 - continue; 162 } 163 } 164 + } /* for */ 165 231 | status = __gss_convert_name_to_union_name(&temp_minor_status, mech, 232 | internal_name, 233 | (gss_name_t *) &union_name); 166 | /* ensure that we have at least one credential element */ 167 | if (creds->count < 1) { 168 | free(creds); 169 + return (major); 170 } 171 172 /* 237 | * Now allocate the creds struct, which will be cast as a gss_cred_id_t 238 | * and returned in the output_cred_handle argument. If there were 173 | * fill in output parameters 174 | * setup the actual mechs output parameter 239 - * no credentials found, return an error. Also, allocate the 240 - * actual_mechs data. 242 - if (creds_acquired == 0) { 243 - free (creds_returned); 244 - return (status); 245 - } 246 - 247 - creds = (gss_union_cred_t) malloc(sizeof(gss_union_cred_desc)); 248 - 249 - creds->count = creds_acquired; 250 - 251 - creds->mechs_array = (gss_OID) 252 - malloc(sizeof(gss_OID_desc) * creds_acquired); 253 - 254 - creds->cred_array = (gss_cred_id_t *) 255 - malloc(sizeof(gss_cred_id_t) * creds_acquired); 256 - 175 */ 176 if (actual_mechs != NULL) { 258 | *actual_mechs = (gss_OID_set) malloc(sizeof(gss_OID_set_desc)); 259 | 260 | (*actual_mechs)->count = creds_acquired; 261 | 262 | (*actual_mechs)->elements = (gss_OID) 263 | malloc(sizeof(gss_OID_desc) * creds_acquired); 177 | if ((*actual_mechs = create_actual_mechs(creds->mechs_array, 178 | creds->count)) == NULL) { 179 | (void) gss_release_cred(minor_status, 180 | (gss_cred_id_t *)&creds); 181 | *minor_status = 0; 182 | return (GSS_S_FAILURE); 265 - 266 - /* 267 - * copy the mechanisms found and their allocated credentials into the 268 - * creds structure. At the same time, build up the actual_mechs 269 - * data. 270 - */ 271 - 272 - j = 0; 273 - 274 - for (i=0; i<desired_mechs->count; i++) { 275 - if(creds_returned[i].available) { 276 - 277 - creds->mechs_array[j].length = 278 - desired_mechs->elements[i].length; 279 - creds->mechs_array[j].elements = (void *) 280 - malloc(desired_mechs->elements[i].length); 281 - memcpy(creds->mechs_array[j].elements, 282 - desired_mechs->elements[i].elements, 283 - desired_mechs->elements[i].length); 284 - creds->cred_array[j] = creds_returned[i].cred; 285 - if (actual_mechs) { 286 - (*actual_mechs)->elements[j].length = 287 - desired_mechs->elements[i].length; 288 - (*actual_mechs)->elements[j].elements = (void *) 289 - malloc(desired_mechs->elements[i].length); 290 - memcpy((*actual_mechs)->elements[j].elements, 291 - desired_mechs->elements[i].elements, 292 - desired_mechs->elements[i].length); 183 } 294 - j++; 295 - } 296 - } 184 } 185 298 | /* free the creds_returned struct, since we are done with it. */ 186 | if (time_rec) 187 + *time_rec = outTime; 300 - free(creds_returned); 188 302 - /* record the information needed for gss_inquire_cred() */ 303 - 304 - creds->auxinfo.creation_time = time(0); 305 - creds->auxinfo.time_rec = temp_time_rec; 306 - creds->auxinfo.cred_usage = cred_usage; 307 - 308 - /* 309 - * we can't just record the internal name, desired_name, since 310 - * it may be destroyed between now and the time gss_inquire_cred() 311 - * is called. So we must record the printable name in a 312 - * gss_buffer_t, calling gss_display_name() to fill it in. When 313 - * gss_inquire_name() is called, we must then call gss_import_name() 314 - * to get the internal name that is required at that point. 315 - */ 316 - if (desired_name) { 317 - status = gss_display_name(&temp_minor_status, desired_name, 318 - &creds->auxinfo.name, 319 - &creds->auxinfo.name_type); 320 - if (status) { 321 - status = GSS_S_BAD_NAME; 322 - goto error_out; 323 - } 324 - } else { 325 - status = gss_display_name(&temp_minor_status, union_name, 326 - &creds->auxinfo.name, 327 - &creds->auxinfo.name_type); 328 - if (status) { 329 - status = GSS_S_BAD_NAME; 330 - goto error_out; 331 - } 332 - } 333 - 189 190 *output_cred_handle = (gss_cred_id_t)creds; 336 - 337 - error_out: 338 - for (k=0; k < creds->count; k++) { 339 - free(creds->mechs_array[k].elements); 340 - if (actual_mechs) 341 - free((*actual_mechs)->elements[k].elements); 191 return (GSS_S_COMPLETE); 192 } 344 - if (actual_mechs) { 345 - free((*actual_mechs)->elements); 346 - free(*actual_mechs); 347 - *actual_mechs = GSS_C_NULL_OID_SET; 348 - } 349 - free(creds->cred_array); 350 - free(creds->mechs_array); 351 - free(creds); 352 - 353 - return(status); 354 - } 355 - 193 194 /* V2 INTERFACE */ 195 OM_uint32 196 gss_add_cred(minor_status, input_cred_handle, 197 desired_name, desired_mech, cred_usage, 198 initiator_time_req, acceptor_time_req, 199 output_cred_handle, actual_mechs, 200 initiator_time_rec, acceptor_time_rec) 201 OM_uint32 *minor_status; 202 const gss_cred_id_t input_cred_handle; 203 const gss_name_t desired_name; 204 const gss_OID desired_mech; 205 gss_cred_usage_t cred_usage; 206 OM_uint32 initiator_time_req; 207 OM_uint32 acceptor_time_req; 208 gss_cred_id_t *output_cred_handle; 209 gss_OID_set *actual_mechs; 210 OM_uint32 *initiator_time_rec; 211 OM_uint32 *acceptor_time_rec; 212 { 213 OM_uint32 status, time_req, time_rec, temp_minor_status; 214 gss_mechanism mech; 215 gss_union_name_t union_name = NULL; 216 gss_union_cred_t union_cred, new_union_cred; 217 gss_name_t internal_name = GSS_C_NO_NAME; 218 gss_name_t allocated_name = GSS_C_NO_NAME; 219 gss_cred_id_t cred = NULL; 220 gss_OID new_mechs_array = NULL; 221 gss_cred_id_t *new_cred_array = NULL; 222 385 | if (input_cred_handle == GSS_C_NO_CREDENTIAL) 386 | return (GSS_S_NO_CRED); 223 | /* check input parameters */ 224 | if (minor_status == NULL) 225 + return (GSS_S_CALL_INACCESSIBLE_WRITE); 226 + *minor_status = 0; 227 388 | union_cred = (gss_union_cred_t) input_cred_handle; 228 | if (input_cred_handle == GSS_C_NO_CREDENTIAL && 229 + output_cred_handle == NULL) 230 + return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); 231 232 + if (output_cred_handle) 233 + *output_cred_handle = GSS_C_NO_CREDENTIAL; 234 + 235 + if (actual_mechs) 236 + *actual_mechs = NULL; 237 + 238 + if (acceptor_time_rec) 239 + *acceptor_time_rec = 0; 240 + 241 + if (initiator_time_rec) 242 + *initiator_time_rec = 0; 243 + 244 mech = __gss_get_mechanism(desired_mech); 245 if (!mech) 246 return (GSS_S_BAD_MECH); 247 + else if (!mech->gss_acquire_cred) 248 + return (GSS_S_UNAVAILABLE); 249 250 + if (input_cred_handle == GSS_C_NO_CREDENTIAL) { 251 + union_cred = malloc(sizeof (gss_union_cred_desc)); 252 + if (union_cred == NULL) 253 + return (GSS_S_FAILURE); 254 + 255 + (void) memset(union_cred, 0, sizeof (gss_union_cred_desc)); 256 + 257 + /* for default credentials we will use GSS_C_NO_NAME */ 258 + internal_name = GSS_C_NO_NAME; 259 + } else { 260 + union_cred = (gss_union_cred_t)input_cred_handle; 261 if (__gss_get_mechanism_cred(union_cred, desired_mech) != 262 GSS_C_NO_CREDENTIAL) 396 | return GSS_S_DUPLICATE_ELEMENT; 263 | return (GSS_S_DUPLICATE_ELEMENT); 264 265 + /* may need to create a mechanism specific name */ 266 + if (desired_name) { 267 union_name = (gss_union_name_t)desired_name; 399 | if (union_name->mech_type) { 400 | if (!g_OID_equal(desired_mech, union_name->mech_type)) 401 | return GSS_S_BAD_NAMETYPE; 268 | if (union_name->mech_type && 269 | g_OID_equal(union_name->mech_type, 270 | &mech->mech_type)) 271 internal_name = union_name->mech_name; 403 | } else { 404 | if (__gss_import_internal_name(minor_status, desired_mech, 405 | union_name, &internal_name)) 272 | else { 273 | if (__gss_import_internal_name(minor_status, 274 | &mech->mech_type, union_name, 275 + &allocated_name) != GSS_S_COMPLETE) 276 return (GSS_S_BAD_NAME); 277 + internal_name = allocated_name; 278 } 279 + } 280 + } 281 282 + 283 if (cred_usage == GSS_C_ACCEPT) 284 time_req = acceptor_time_req; 285 else if (cred_usage == GSS_C_INITIATE) 286 time_req = initiator_time_req; 287 else if (cred_usage == GSS_C_BOTH) 288 time_req = (acceptor_time_req > initiator_time_req) ? 289 acceptor_time_req : initiator_time_req; 290 291 status = mech->gss_acquire_cred(mech->context, minor_status, 292 internal_name, time_req, 293 GSS_C_NULL_OID_SET, cred_usage, 294 &cred, NULL, &time_rec); 295 + 296 if (status != GSS_S_COMPLETE) 297 goto errout; 298 299 + /* may need to set credential auxinfo strucutre */ 300 + if (union_cred->auxinfo.creation_time == 0) { 301 + union_cred->auxinfo.creation_time = time(NULL); 302 + union_cred->auxinfo.time_rec = time_rec; 303 + union_cred->auxinfo.cred_usage = cred_usage; 304 + 305 + /* 306 + * we must set the name; if name is not supplied 307 + * we must do inquire cred to get it 308 + */ 309 + if (internal_name == NULL) { 310 + if (mech->gss_inquire_cred == NULL || 311 + ((status = mech->gss_inquire_cred( 312 + mech->context, 313 + &temp_minor_status, cred, 314 + &allocated_name, NULL, NULL, 315 + NULL)) != GSS_S_COMPLETE)) 316 + goto errout; 317 + internal_name = allocated_name; 318 + } 319 + 320 + if ((status = mech->gss_display_name(mech->context, 321 + &temp_minor_status, internal_name, 322 + &union_cred->auxinfo.name, 323 + &union_cred->auxinfo.name_type)) != 324 + GSS_S_COMPLETE) 325 + goto errout; 326 + } 327 + 328 + /* now add the new credential elements */ 329 new_mechs_array = (gss_OID) 330 malloc(sizeof (gss_OID_desc) * (union_cred->count+1)); 331 332 new_cred_array = (gss_cred_id_t *) 333 malloc(sizeof (gss_cred_id_t) * (union_cred->count+1)); 334 431 - *minor_status = ENOMEM; 335 if (!new_mechs_array || !new_cred_array) { 336 status = GSS_S_FAILURE; 337 goto errout; 338 } 436 - 339 340 if (acceptor_time_rec) 341 if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) 342 *acceptor_time_rec = time_rec; 343 if (initiator_time_rec) 344 if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) 345 *initiator_time_rec = time_rec; 346 347 /* 445 | * OK, expand the mechanism array in the union credentials 348 | * OK, expand the mechanism array and the credential array 446 - * (Look for the union label...) 349 */ 448 | memcpy(new_mechs_array, union_cred->mechs_array, 350 | (void) memcpy(new_mechs_array, union_cred->mechs_array, 351 sizeof (gss_OID_desc) * union_cred->count); 450 | memcpy(new_cred_array, union_cred->cred_array, 352 | (void) memcpy(new_cred_array, union_cred->cred_array, 353 sizeof (gss_cred_id_t) * union_cred->count); 354 355 new_cred_array[union_cred->count] = cred; 454 | new_mechs_array[union_cred->count].length = desired_mech->length; 455 | new_mechs_array[union_cred->count].elements = malloc(desired_mech->length); 356 | if ((new_mechs_array[union_cred->count].elements = 357 | malloc(mech->mech_type.length)) == NULL) 456 - if (!new_mechs_array[union_cred->count].elements) { 457 - *minor_status = ENOMEM; 358 goto errout; 359 + 360 + g_OID_copy(&new_mechs_array[union_cred->count], 361 + &mech->mech_type); 362 + 363 + if (actual_mechs) { 364 + *actual_mechs = create_actual_mechs(new_mechs_array, 365 + union_cred->count + 1); 366 + if (*actual_mechs == NULL) { 367 + free(new_mechs_array[union_cred->count].elements); 368 + goto errout; 369 } 460 | memcpy(new_mechs_array[union_cred->count].elements, desired_mech->elements, 370 | } 461 - desired_mech->length); 371 372 if (output_cred_handle == NULL) { 373 free(union_cred->mechs_array); 374 free(union_cred->cred_array); 375 new_union_cred = union_cred; 376 } else { 377 new_union_cred = malloc(sizeof (gss_union_cred_desc)); 378 if (new_union_cred == NULL) { 470 | *minor_status = ENOMEM; 379 | free(new_mechs_array[union_cred->count].elements); 380 goto errout; 381 } 382 *new_union_cred = *union_cred; 474 | *output_cred_handle = new_union_cred; 383 | *output_cred_handle = (gss_cred_id_t)new_union_cred; 384 } 385 + 386 new_union_cred->mechs_array = new_mechs_array; 387 new_union_cred->cred_array = new_cred_array; 479 - new_mechs_array = 0; 480 - new_cred_array = 0; 388 new_union_cred->count++; 389 482 | if (actual_mechs) 390 | /* We're done with the internal name. Free it if we allocated it. */ 483 - *actual_mechs = create_actual_mechs(new_union_cred); 391 485 | status = GSS_S_COMPLETE; 392 | if (allocated_name) 393 + (void) __gss_release_internal_name(&temp_minor_status, 394 + &mech->mech_type, 395 + &allocated_name); 396 397 + return (GSS_S_COMPLETE); 398 + 399 errout: 400 if (new_mechs_array) 401 free(new_mechs_array); 402 if (new_cred_array) 403 free(new_cred_array); 492 | if (!union_name->mech_type) { 404 | 405 + if (cred != NULL && mech->gss_release_cred) 406 + mech->gss_release_cred(mech->context, 407 + &temp_minor_status, &cred); 408 + 409 + if (allocated_name) 410 (void) __gss_release_internal_name(&temp_minor_status, 494 | desired_mech, &internal_name); 411 | &mech->mech_type, 412 + &allocated_name); 413 + 414 + if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) { 415 + if (union_cred->auxinfo.name.value) 416 + free(union_cred->auxinfo.name.value); 417 + free(union_cred); 418 } 419 420 return (status); 421 } ----Unchanged portion omitted----