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*9698SPeter.Shoults@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 270Sstevel@tonic-gate * glue routine for gss_acquire_cred 280Sstevel@tonic-gate */ 290Sstevel@tonic-gate #include <mechglueP.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 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 77*9698SPeter.Shoults@Sun.COM static OM_uint32 78*9698SPeter.Shoults@Sun.COM val_acq_cred_args( 79*9698SPeter.Shoults@Sun.COM OM_uint32 *minor_status, 80*9698SPeter.Shoults@Sun.COM gss_cred_id_t *output_cred_handle, 81*9698SPeter.Shoults@Sun.COM gss_OID_set *actual_mechs, 82*9698SPeter.Shoults@Sun.COM OM_uint32 *time_rec) 83*9698SPeter.Shoults@Sun.COM { 84*9698SPeter.Shoults@Sun.COM 85*9698SPeter.Shoults@Sun.COM /* Initialize outputs. */ 86*9698SPeter.Shoults@Sun.COM 87*9698SPeter.Shoults@Sun.COM if (minor_status != NULL) 88*9698SPeter.Shoults@Sun.COM *minor_status = 0; 89*9698SPeter.Shoults@Sun.COM 90*9698SPeter.Shoults@Sun.COM if (output_cred_handle != NULL) 91*9698SPeter.Shoults@Sun.COM *output_cred_handle = GSS_C_NO_CREDENTIAL; 92*9698SPeter.Shoults@Sun.COM 93*9698SPeter.Shoults@Sun.COM if (actual_mechs != NULL) 94*9698SPeter.Shoults@Sun.COM *actual_mechs = GSS_C_NULL_OID_SET; 95*9698SPeter.Shoults@Sun.COM 96*9698SPeter.Shoults@Sun.COM if (time_rec != NULL) 97*9698SPeter.Shoults@Sun.COM *time_rec = 0; 98*9698SPeter.Shoults@Sun.COM 99*9698SPeter.Shoults@Sun.COM /* Validate arguments. */ 100*9698SPeter.Shoults@Sun.COM 101*9698SPeter.Shoults@Sun.COM if (minor_status == NULL) 102*9698SPeter.Shoults@Sun.COM return (GSS_S_CALL_INACCESSIBLE_WRITE); 103*9698SPeter.Shoults@Sun.COM 104*9698SPeter.Shoults@Sun.COM if (output_cred_handle == NULL) 105*9698SPeter.Shoults@Sun.COM return (GSS_S_CALL_INACCESSIBLE_WRITE); 106*9698SPeter.Shoults@Sun.COM 107*9698SPeter.Shoults@Sun.COM return (GSS_S_COMPLETE); 108*9698SPeter.Shoults@Sun.COM } 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate OM_uint32 1110Sstevel@tonic-gate gss_acquire_cred(minor_status, 1120Sstevel@tonic-gate desired_name, 1130Sstevel@tonic-gate time_req, 1140Sstevel@tonic-gate desired_mechs, 1150Sstevel@tonic-gate cred_usage, 1160Sstevel@tonic-gate output_cred_handle, 1170Sstevel@tonic-gate actual_mechs, 1180Sstevel@tonic-gate time_rec) 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate OM_uint32 * minor_status; 1210Sstevel@tonic-gate const gss_name_t desired_name; 1220Sstevel@tonic-gate OM_uint32 time_req; 1230Sstevel@tonic-gate const gss_OID_set desired_mechs; 1240Sstevel@tonic-gate int cred_usage; 1250Sstevel@tonic-gate gss_cred_id_t *output_cred_handle; 1260Sstevel@tonic-gate gss_OID_set * actual_mechs; 1270Sstevel@tonic-gate OM_uint32 * time_rec; 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate { 1300Sstevel@tonic-gate OM_uint32 major = GSS_S_FAILURE; 1310Sstevel@tonic-gate OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE; 1320Sstevel@tonic-gate gss_OID_set_desc default_OID_set; 1330Sstevel@tonic-gate gss_OID_set mechs; 1340Sstevel@tonic-gate gss_OID_desc default_OID; 1350Sstevel@tonic-gate gss_mechanism mech; 1360Sstevel@tonic-gate int i; 1370Sstevel@tonic-gate gss_union_cred_t creds; 1380Sstevel@tonic-gate 139*9698SPeter.Shoults@Sun.COM major = val_acq_cred_args(minor_status, 140*9698SPeter.Shoults@Sun.COM output_cred_handle, 141*9698SPeter.Shoults@Sun.COM actual_mechs, 142*9698SPeter.Shoults@Sun.COM time_rec); 143*9698SPeter.Shoults@Sun.COM if (major != GSS_S_COMPLETE) 144*9698SPeter.Shoults@Sun.COM return (major); 1450Sstevel@tonic-gate 146*9698SPeter.Shoults@Sun.COM /* Initial value needed below. */ 147*9698SPeter.Shoults@Sun.COM major = GSS_S_FAILURE; 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate /* 1500Sstevel@tonic-gate * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an 1510Sstevel@tonic-gate * appropriate default. We use the first mechanism in the 1520Sstevel@tonic-gate * mechansim list as the default. This set is created with 1530Sstevel@tonic-gate * statics thus needs not be freed 1540Sstevel@tonic-gate */ 1550Sstevel@tonic-gate if (desired_mechs == GSS_C_NULL_OID_SET) { 1560Sstevel@tonic-gate mech = __gss_get_mechanism(NULL); 1570Sstevel@tonic-gate if (mech == NULL) 1580Sstevel@tonic-gate return (GSS_S_BAD_MECH); 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate mechs = &default_OID_set; 1610Sstevel@tonic-gate default_OID_set.count = 1; 1620Sstevel@tonic-gate default_OID_set.elements = &default_OID; 1630Sstevel@tonic-gate default_OID.length = mech->mech_type.length; 1640Sstevel@tonic-gate default_OID.elements = mech->mech_type.elements; 1650Sstevel@tonic-gate } else 1660Sstevel@tonic-gate mechs = desired_mechs; 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate if (mechs->count == NULL) 1690Sstevel@tonic-gate return (GSS_S_BAD_MECH); 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate /* allocate the output credential structure */ 1720Sstevel@tonic-gate creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc)); 1730Sstevel@tonic-gate if (creds == NULL) 1740Sstevel@tonic-gate return (GSS_S_FAILURE); 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate /* initialize to 0s */ 1770Sstevel@tonic-gate (void) memset(creds, 0, sizeof (gss_union_cred_desc)); 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate /* for each requested mech attempt to obtain a credential */ 1800Sstevel@tonic-gate for (i = 0; i < mechs->count; i++) { 1810Sstevel@tonic-gate major = gss_add_cred(minor_status, (gss_cred_id_t)creds, 1820Sstevel@tonic-gate desired_name, 1830Sstevel@tonic-gate &mechs->elements[i], 1840Sstevel@tonic-gate cred_usage, time_req, time_req, NULL, 1850Sstevel@tonic-gate NULL, &initTimeOut, &acceptTimeOut); 1860Sstevel@tonic-gate if (major == GSS_S_COMPLETE) { 1870Sstevel@tonic-gate /* update the credential's time */ 1880Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT) { 1890Sstevel@tonic-gate if (outTime > acceptTimeOut) 1900Sstevel@tonic-gate outTime = acceptTimeOut; 1910Sstevel@tonic-gate } else if (cred_usage == GSS_C_INITIATE) { 1920Sstevel@tonic-gate if (outTime > initTimeOut) 1930Sstevel@tonic-gate outTime = initTimeOut; 1940Sstevel@tonic-gate } else { 1950Sstevel@tonic-gate /* 1960Sstevel@tonic-gate * time_rec is the lesser of the 1970Sstevel@tonic-gate * init/accept times 1980Sstevel@tonic-gate */ 1990Sstevel@tonic-gate if (initTimeOut > acceptTimeOut) 2000Sstevel@tonic-gate outTime = (outTime > acceptTimeOut) ? 2010Sstevel@tonic-gate acceptTimeOut : outTime; 2020Sstevel@tonic-gate else 2030Sstevel@tonic-gate outTime = (outTime > initTimeOut) ? 2040Sstevel@tonic-gate initTimeOut : outTime; 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate } 2070Sstevel@tonic-gate } /* for */ 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate /* ensure that we have at least one credential element */ 2100Sstevel@tonic-gate if (creds->count < 1) { 2110Sstevel@tonic-gate free(creds); 2120Sstevel@tonic-gate return (major); 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate /* 2160Sstevel@tonic-gate * fill in output parameters 2170Sstevel@tonic-gate * setup the actual mechs output parameter 2180Sstevel@tonic-gate */ 2190Sstevel@tonic-gate if (actual_mechs != NULL) { 2200Sstevel@tonic-gate if ((*actual_mechs = create_actual_mechs(creds->mechs_array, 2210Sstevel@tonic-gate creds->count)) == NULL) { 2220Sstevel@tonic-gate (void) gss_release_cred(minor_status, 2230Sstevel@tonic-gate (gss_cred_id_t *)&creds); 2240Sstevel@tonic-gate *minor_status = 0; 2250Sstevel@tonic-gate return (GSS_S_FAILURE); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate if (time_rec) 2300Sstevel@tonic-gate *time_rec = outTime; 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate *output_cred_handle = (gss_cred_id_t)creds; 2340Sstevel@tonic-gate return (GSS_S_COMPLETE); 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate 237*9698SPeter.Shoults@Sun.COM static OM_uint32 238*9698SPeter.Shoults@Sun.COM val_add_cred_args( 239*9698SPeter.Shoults@Sun.COM OM_uint32 *minor_status, 240*9698SPeter.Shoults@Sun.COM gss_cred_id_t input_cred_handle, 241*9698SPeter.Shoults@Sun.COM gss_cred_id_t *output_cred_handle, 242*9698SPeter.Shoults@Sun.COM gss_OID_set *actual_mechs, 243*9698SPeter.Shoults@Sun.COM OM_uint32 *initiator_time_rec, 244*9698SPeter.Shoults@Sun.COM OM_uint32 *acceptor_time_rec) 245*9698SPeter.Shoults@Sun.COM { 246*9698SPeter.Shoults@Sun.COM 247*9698SPeter.Shoults@Sun.COM /* Initialize outputs. */ 248*9698SPeter.Shoults@Sun.COM 249*9698SPeter.Shoults@Sun.COM if (minor_status != NULL) 250*9698SPeter.Shoults@Sun.COM *minor_status = 0; 251*9698SPeter.Shoults@Sun.COM 252*9698SPeter.Shoults@Sun.COM if (output_cred_handle != NULL) 253*9698SPeter.Shoults@Sun.COM *output_cred_handle = GSS_C_NO_CREDENTIAL; 254*9698SPeter.Shoults@Sun.COM 255*9698SPeter.Shoults@Sun.COM if (actual_mechs != NULL) 256*9698SPeter.Shoults@Sun.COM *actual_mechs = GSS_C_NO_OID_SET; 257*9698SPeter.Shoults@Sun.COM 258*9698SPeter.Shoults@Sun.COM if (acceptor_time_rec != NULL) 259*9698SPeter.Shoults@Sun.COM *acceptor_time_rec = 0; 260*9698SPeter.Shoults@Sun.COM 261*9698SPeter.Shoults@Sun.COM if (initiator_time_rec != NULL) 262*9698SPeter.Shoults@Sun.COM *initiator_time_rec = 0; 263*9698SPeter.Shoults@Sun.COM 264*9698SPeter.Shoults@Sun.COM /* Validate arguments. */ 265*9698SPeter.Shoults@Sun.COM 266*9698SPeter.Shoults@Sun.COM if (minor_status == NULL) 267*9698SPeter.Shoults@Sun.COM return (GSS_S_CALL_INACCESSIBLE_WRITE); 268*9698SPeter.Shoults@Sun.COM 269*9698SPeter.Shoults@Sun.COM if (input_cred_handle == GSS_C_NO_CREDENTIAL && 270*9698SPeter.Shoults@Sun.COM output_cred_handle == NULL) 271*9698SPeter.Shoults@Sun.COM 272*9698SPeter.Shoults@Sun.COM return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); 273*9698SPeter.Shoults@Sun.COM 274*9698SPeter.Shoults@Sun.COM return (GSS_S_COMPLETE); 275*9698SPeter.Shoults@Sun.COM } 276*9698SPeter.Shoults@Sun.COM 2770Sstevel@tonic-gate /* V2 INTERFACE */ 2780Sstevel@tonic-gate OM_uint32 2790Sstevel@tonic-gate gss_add_cred(minor_status, input_cred_handle, 2800Sstevel@tonic-gate desired_name, desired_mech, cred_usage, 2810Sstevel@tonic-gate initiator_time_req, acceptor_time_req, 2820Sstevel@tonic-gate output_cred_handle, actual_mechs, 2830Sstevel@tonic-gate initiator_time_rec, acceptor_time_rec) 2840Sstevel@tonic-gate OM_uint32 *minor_status; 2850Sstevel@tonic-gate const gss_cred_id_t input_cred_handle; 2860Sstevel@tonic-gate const gss_name_t desired_name; 2870Sstevel@tonic-gate const gss_OID desired_mech; 2880Sstevel@tonic-gate gss_cred_usage_t cred_usage; 2890Sstevel@tonic-gate OM_uint32 initiator_time_req; 2900Sstevel@tonic-gate OM_uint32 acceptor_time_req; 2910Sstevel@tonic-gate gss_cred_id_t *output_cred_handle; 2920Sstevel@tonic-gate gss_OID_set *actual_mechs; 2930Sstevel@tonic-gate OM_uint32 *initiator_time_rec; 2940Sstevel@tonic-gate OM_uint32 *acceptor_time_rec; 2950Sstevel@tonic-gate { 2960Sstevel@tonic-gate OM_uint32 status, time_req, time_rec, temp_minor_status; 2970Sstevel@tonic-gate gss_mechanism mech; 2980Sstevel@tonic-gate gss_union_name_t union_name = NULL; 2990Sstevel@tonic-gate gss_union_cred_t union_cred, new_union_cred; 3000Sstevel@tonic-gate gss_name_t internal_name = GSS_C_NO_NAME; 3010Sstevel@tonic-gate gss_name_t allocated_name = GSS_C_NO_NAME; 3020Sstevel@tonic-gate gss_cred_id_t cred = NULL; 3030Sstevel@tonic-gate gss_OID new_mechs_array = NULL; 3040Sstevel@tonic-gate gss_cred_id_t *new_cred_array = NULL; 3050Sstevel@tonic-gate 306*9698SPeter.Shoults@Sun.COM status = val_add_cred_args(minor_status, 307*9698SPeter.Shoults@Sun.COM input_cred_handle, 308*9698SPeter.Shoults@Sun.COM output_cred_handle, 309*9698SPeter.Shoults@Sun.COM actual_mechs, 310*9698SPeter.Shoults@Sun.COM initiator_time_rec, 311*9698SPeter.Shoults@Sun.COM acceptor_time_rec); 312*9698SPeter.Shoults@Sun.COM if (status != GSS_S_COMPLETE) 313*9698SPeter.Shoults@Sun.COM return (status); 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate mech = __gss_get_mechanism(desired_mech); 3160Sstevel@tonic-gate if (!mech) 3170Sstevel@tonic-gate return (GSS_S_BAD_MECH); 3180Sstevel@tonic-gate else if (!mech->gss_acquire_cred) 3190Sstevel@tonic-gate return (GSS_S_UNAVAILABLE); 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate if (input_cred_handle == GSS_C_NO_CREDENTIAL) { 3220Sstevel@tonic-gate union_cred = malloc(sizeof (gss_union_cred_desc)); 3230Sstevel@tonic-gate if (union_cred == NULL) 3240Sstevel@tonic-gate return (GSS_S_FAILURE); 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate (void) memset(union_cred, 0, sizeof (gss_union_cred_desc)); 327160Swyllys } else { 328160Swyllys /* Input Cred is non-NULL */ 329160Swyllys union_cred = (gss_union_cred_t)input_cred_handle; 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate if (__gss_get_mechanism_cred(union_cred, desired_mech) != 332160Swyllys GSS_C_NO_CREDENTIAL) { 333160Swyllys status = GSS_S_DUPLICATE_ELEMENT; 334160Swyllys goto errout; 335160Swyllys } 3360Sstevel@tonic-gate 337160Swyllys /* 338160Swyllys * If no name was given, determine the name from the 339160Swyllys * existing credential. 340160Swyllys */ 341160Swyllys if (desired_name == GSS_C_NO_NAME) { 342160Swyllys if (gss_import_name(minor_status, 343160Swyllys &union_cred->auxinfo.name, 344160Swyllys union_cred->auxinfo.name_type, 345160Swyllys &allocated_name) == GSS_S_COMPLETE && 346160Swyllys (gss_canonicalize_name(minor_status, 347160Swyllys allocated_name, 348160Swyllys &mech->mech_type, 349160Swyllys NULL) == GSS_S_COMPLETE)) { 3500Sstevel@tonic-gate internal_name = allocated_name; 3510Sstevel@tonic-gate } 352160Swyllys } /* else, get the name from the desired_name below */ 353160Swyllys } 354160Swyllys if (desired_name != GSS_C_NO_NAME) { 355160Swyllys /* may need to create a mechanism specific name */ 356160Swyllys union_name = (gss_union_name_t)desired_name; 357160Swyllys 358160Swyllys if (union_name->mech_type && 359160Swyllys g_OID_equal(union_name->mech_type, 360160Swyllys &mech->mech_type)) 361160Swyllys internal_name = union_name->mech_name; 362160Swyllys else { 363160Swyllys if (__gss_import_internal_name(minor_status, 364160Swyllys &mech->mech_type, union_name, 365160Swyllys &allocated_name) != GSS_S_COMPLETE) { 366160Swyllys status = GSS_S_BAD_NAME; 367160Swyllys goto errout; 368160Swyllys } 369160Swyllys internal_name = allocated_name; 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT) 3740Sstevel@tonic-gate time_req = acceptor_time_req; 3750Sstevel@tonic-gate else if (cred_usage == GSS_C_INITIATE) 3760Sstevel@tonic-gate time_req = initiator_time_req; 3770Sstevel@tonic-gate else if (cred_usage == GSS_C_BOTH) 3780Sstevel@tonic-gate time_req = (acceptor_time_req > initiator_time_req) ? 3790Sstevel@tonic-gate acceptor_time_req : initiator_time_req; 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate status = mech->gss_acquire_cred(mech->context, minor_status, 3820Sstevel@tonic-gate internal_name, time_req, 3830Sstevel@tonic-gate GSS_C_NULL_OID_SET, cred_usage, 3840Sstevel@tonic-gate &cred, NULL, &time_rec); 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate if (status != GSS_S_COMPLETE) 3870Sstevel@tonic-gate goto errout; 3880Sstevel@tonic-gate 389160Swyllys /* may need to set credential auxinfo structure */ 3900Sstevel@tonic-gate if (union_cred->auxinfo.creation_time == 0) { 3910Sstevel@tonic-gate union_cred->auxinfo.creation_time = time(NULL); 3920Sstevel@tonic-gate union_cred->auxinfo.time_rec = time_rec; 3930Sstevel@tonic-gate union_cred->auxinfo.cred_usage = cred_usage; 3940Sstevel@tonic-gate 3953376Smp153739 /* 3963376Smp153739 * If internal_name is GSS_C_NO_NAME a cred with no associated 3973376Smp153739 * name was requested: don't set auxinfo.name or auxinfo.name_type. 3983376Smp153739 */ 3993376Smp153739 if (internal_name != GSS_C_NO_NAME) { 4003376Smp153739 if ((status = mech->gss_display_name(mech->context, 4013376Smp153739 &temp_minor_status, internal_name, 4023376Smp153739 &union_cred->auxinfo.name, 4033376Smp153739 &union_cred->auxinfo.name_type)) != 4043376Smp153739 GSS_S_COMPLETE) 4050Sstevel@tonic-gate goto errout; 4060Sstevel@tonic-gate } 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate /* now add the new credential elements */ 4100Sstevel@tonic-gate new_mechs_array = (gss_OID) 4110Sstevel@tonic-gate malloc(sizeof (gss_OID_desc) * (union_cred->count+1)); 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate new_cred_array = (gss_cred_id_t *) 4140Sstevel@tonic-gate malloc(sizeof (gss_cred_id_t) * (union_cred->count+1)); 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate if (!new_mechs_array || !new_cred_array) { 4170Sstevel@tonic-gate status = GSS_S_FAILURE; 4180Sstevel@tonic-gate goto errout; 4190Sstevel@tonic-gate } 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate if (acceptor_time_rec) 4220Sstevel@tonic-gate if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) 4230Sstevel@tonic-gate *acceptor_time_rec = time_rec; 4240Sstevel@tonic-gate if (initiator_time_rec) 4250Sstevel@tonic-gate if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) 4260Sstevel@tonic-gate *initiator_time_rec = time_rec; 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate /* 4290Sstevel@tonic-gate * OK, expand the mechanism array and the credential array 4300Sstevel@tonic-gate */ 4310Sstevel@tonic-gate (void) memcpy(new_mechs_array, union_cred->mechs_array, 4320Sstevel@tonic-gate sizeof (gss_OID_desc) * union_cred->count); 4330Sstevel@tonic-gate (void) memcpy(new_cred_array, union_cred->cred_array, 4340Sstevel@tonic-gate sizeof (gss_cred_id_t) * union_cred->count); 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate new_cred_array[union_cred->count] = cred; 4370Sstevel@tonic-gate if ((new_mechs_array[union_cred->count].elements = 4380Sstevel@tonic-gate malloc(mech->mech_type.length)) == NULL) 4390Sstevel@tonic-gate goto errout; 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate g_OID_copy(&new_mechs_array[union_cred->count], 4420Sstevel@tonic-gate &mech->mech_type); 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate if (actual_mechs) { 4450Sstevel@tonic-gate *actual_mechs = create_actual_mechs(new_mechs_array, 4460Sstevel@tonic-gate union_cred->count + 1); 4470Sstevel@tonic-gate if (*actual_mechs == NULL) { 4480Sstevel@tonic-gate free(new_mechs_array[union_cred->count].elements); 4490Sstevel@tonic-gate goto errout; 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate if (output_cred_handle == NULL) { 4540Sstevel@tonic-gate free(union_cred->mechs_array); 4550Sstevel@tonic-gate free(union_cred->cred_array); 4560Sstevel@tonic-gate new_union_cred = union_cred; 4570Sstevel@tonic-gate } else { 4580Sstevel@tonic-gate new_union_cred = malloc(sizeof (gss_union_cred_desc)); 4590Sstevel@tonic-gate if (new_union_cred == NULL) { 4600Sstevel@tonic-gate free(new_mechs_array[union_cred->count].elements); 4610Sstevel@tonic-gate goto errout; 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate *new_union_cred = *union_cred; 4640Sstevel@tonic-gate *output_cred_handle = (gss_cred_id_t)new_union_cred; 4650Sstevel@tonic-gate } 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate new_union_cred->mechs_array = new_mechs_array; 4680Sstevel@tonic-gate new_union_cred->cred_array = new_cred_array; 4690Sstevel@tonic-gate new_union_cred->count++; 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate /* We're done with the internal name. Free it if we allocated it. */ 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate if (allocated_name) 4740Sstevel@tonic-gate (void) __gss_release_internal_name(&temp_minor_status, 4750Sstevel@tonic-gate &mech->mech_type, 4760Sstevel@tonic-gate &allocated_name); 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate return (GSS_S_COMPLETE); 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate errout: 4810Sstevel@tonic-gate if (new_mechs_array) 4820Sstevel@tonic-gate free(new_mechs_array); 4830Sstevel@tonic-gate if (new_cred_array) 4840Sstevel@tonic-gate free(new_cred_array); 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate if (cred != NULL && mech->gss_release_cred) 4870Sstevel@tonic-gate mech->gss_release_cred(mech->context, 4880Sstevel@tonic-gate &temp_minor_status, &cred); 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate if (allocated_name) 4910Sstevel@tonic-gate (void) __gss_release_internal_name(&temp_minor_status, 4920Sstevel@tonic-gate &mech->mech_type, 4930Sstevel@tonic-gate &allocated_name); 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) { 4960Sstevel@tonic-gate if (union_cred->auxinfo.name.value) 4970Sstevel@tonic-gate free(union_cred->auxinfo.name.value); 4980Sstevel@tonic-gate free(union_cred); 4990Sstevel@tonic-gate } 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate return (status); 5020Sstevel@tonic-gate } 503