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 51914Scasper * Common Development and Distribution License (the "License"). 61914Scasper * 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 * This file contains functions to initialize the gssapi library and 280Sstevel@tonic-gate * load mechanism libraries. 290Sstevel@tonic-gate * 300Sstevel@tonic-gate * It also contain functions requiring direct access to the mechanism's 310Sstevel@tonic-gate * list (gss_inidicate_mechs and gss_release_oid) as well as support 320Sstevel@tonic-gate * functions which translate the mechanism strings to oids and vise versa. 330Sstevel@tonic-gate * 340Sstevel@tonic-gate * The mechanism libraries are loaded on demand. This is triggered 350Sstevel@tonic-gate * through the get_mechanism function call. 360Sstevel@tonic-gate * 370Sstevel@tonic-gate * Updates to the mechList are performed with the following restrictions: 380Sstevel@tonic-gate * - once a library is loaded, none of the fields are updated 390Sstevel@tonic-gate * - existing entiries for non-loaded mechs, will have the 400Sstevel@tonic-gate * library and kernel module names updated only 410Sstevel@tonic-gate * (i.e. the mech oid and mech name will not be updated) 420Sstevel@tonic-gate */ 430Sstevel@tonic-gate 440Sstevel@tonic-gate #include <mechglueP.h> 450Sstevel@tonic-gate #include <stdio.h> 460Sstevel@tonic-gate #include <syslog.h> 470Sstevel@tonic-gate #include <stdlib.h> 480Sstevel@tonic-gate #include <string.h> 490Sstevel@tonic-gate #include <sys/stat.h> 500Sstevel@tonic-gate #include <ctype.h> 510Sstevel@tonic-gate #include <errno.h> 520Sstevel@tonic-gate #include <synch.h> 530Sstevel@tonic-gate #include <dlfcn.h> 540Sstevel@tonic-gate #include <libintl.h> 550Sstevel@tonic-gate 560Sstevel@tonic-gate 570Sstevel@tonic-gate #ifndef TEXT_DOMAIN 580Sstevel@tonic-gate #error TEXT_DOMAIN not defined 590Sstevel@tonic-gate #endif 600Sstevel@tonic-gate 610Sstevel@tonic-gate #define MECH_CONF "/etc/gss/mech" 620Sstevel@tonic-gate 630Sstevel@tonic-gate #define MECH_LIB_PREFIX1 "/usr/lib/" 640Sstevel@tonic-gate 650Sstevel@tonic-gate /* 660Sstevel@tonic-gate * This #ifdef mess figures out if we are to be compiled into 670Sstevel@tonic-gate * a sparcv9/lp64 binary for the purposes of figuring the absolute location 680Sstevel@tonic-gate * of gss-api mechanism modules. 690Sstevel@tonic-gate */ 700Sstevel@tonic-gate #ifdef _LP64 710Sstevel@tonic-gate 720Sstevel@tonic-gate #ifdef __sparc 730Sstevel@tonic-gate 740Sstevel@tonic-gate #define MECH_LIB_PREFIX2 "sparcv9/" 750Sstevel@tonic-gate 760Sstevel@tonic-gate #elif defined(__amd64) 770Sstevel@tonic-gate 780Sstevel@tonic-gate #define MECH_LIB_PREFIX2 "amd64/" 790Sstevel@tonic-gate 800Sstevel@tonic-gate #else /* __sparc */ 810Sstevel@tonic-gate 820Sstevel@tonic-gate you need to define where under /usr the LP64 libraries live for this platform 830Sstevel@tonic-gate 840Sstevel@tonic-gate #endif /* __sparc */ 850Sstevel@tonic-gate 860Sstevel@tonic-gate #else /* _LP64 */ 870Sstevel@tonic-gate 880Sstevel@tonic-gate #define MECH_LIB_PREFIX2 "" 890Sstevel@tonic-gate 900Sstevel@tonic-gate #endif /* _LP64 */ 910Sstevel@tonic-gate 920Sstevel@tonic-gate #define MECH_LIB_DIR "gss/" 930Sstevel@tonic-gate 940Sstevel@tonic-gate #define MECH_LIB_PREFIX MECH_LIB_PREFIX1 MECH_LIB_PREFIX2 MECH_LIB_DIR 950Sstevel@tonic-gate 960Sstevel@tonic-gate 970Sstevel@tonic-gate #ifndef MECH_SYM 980Sstevel@tonic-gate #define MECH_SYM "gss_mech_initialize" 990Sstevel@tonic-gate #endif 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate #define M_DEFAULT "default" 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate /* Local functions */ 1040Sstevel@tonic-gate static gss_mech_info searchMechList(const gss_OID); 1050Sstevel@tonic-gate static void loadConfigFile(const char *); 1060Sstevel@tonic-gate static void updateMechList(void); 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate /* 1100Sstevel@tonic-gate * list of mechanism libraries and their entry points. 1110Sstevel@tonic-gate * the list also maintains state of the mech libraries (loaded or not). 1120Sstevel@tonic-gate */ 1130Sstevel@tonic-gate static gss_mech_info g_mechList = NULL; 1140Sstevel@tonic-gate static gss_mech_info g_mechListTail = NULL; 1150Sstevel@tonic-gate static mutex_t g_mechListLock; 1160Sstevel@tonic-gate static time_t g_confFileModTime = (time_t)0; 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate /* 1190Sstevel@tonic-gate * function used to reclaim the memory used by a gss_OID structure. 1200Sstevel@tonic-gate * This routine requires direct access to the mechList. 1210Sstevel@tonic-gate */ 1220Sstevel@tonic-gate OM_uint32 1230Sstevel@tonic-gate gss_release_oid(minor_status, oid) 1240Sstevel@tonic-gate OM_uint32 *minor_status; 1250Sstevel@tonic-gate gss_OID *oid; 1260Sstevel@tonic-gate { 1270Sstevel@tonic-gate OM_uint32 major; 1280Sstevel@tonic-gate gss_mech_info aMech = g_mechList; 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate if (minor_status == NULL) 1310Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate *minor_status = 0; 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate while (aMech != NULL) { 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate /* 1380Sstevel@tonic-gate * look through the loaded mechanism libraries for 1390Sstevel@tonic-gate * gss_internal_release_oid until one returns success. 1400Sstevel@tonic-gate * gss_internal_release_oid will only return success when 1410Sstevel@tonic-gate * the OID was recognized as an internal mechanism OID. if no 1420Sstevel@tonic-gate * mechanisms recognize the OID, then call the generic version. 1430Sstevel@tonic-gate */ 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate /* 1460Sstevel@tonic-gate * we can walk the mechanism list without a mutex, because we 1470Sstevel@tonic-gate * are only looking at fields which once read will never change. 1480Sstevel@tonic-gate * Mechanism entries are always added to the end, and as 1490Sstevel@tonic-gate * complete entries. 1500Sstevel@tonic-gate */ 1510Sstevel@tonic-gate if (aMech->mech && aMech->mech->gss_internal_release_oid) { 1520Sstevel@tonic-gate major = aMech->mech->gss_internal_release_oid( 1530Sstevel@tonic-gate aMech->mech->context, 1540Sstevel@tonic-gate minor_status, oid); 1550Sstevel@tonic-gate if (major == GSS_S_COMPLETE) 1560Sstevel@tonic-gate return (GSS_S_COMPLETE); 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate aMech = aMech->next; 1590Sstevel@tonic-gate } /* while */ 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate return (generic_gss_release_oid(minor_status, oid)); 1620Sstevel@tonic-gate } /* gss_release_oid */ 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate /* 1660Sstevel@tonic-gate * this function will return an oid set indicating available mechanisms. 1670Sstevel@tonic-gate * The set returned is based on configuration file entries and 1680Sstevel@tonic-gate * NOT on the loaded mechanisms. This function does not check if any 1690Sstevel@tonic-gate * of these can actually be loaded. 1700Sstevel@tonic-gate * This routine needs direct access to the mechanism list. 1710Sstevel@tonic-gate * To avoid reading the configuration file each call, we will save a 1720Sstevel@tonic-gate * a mech oid set, and only update it once the file has changed. 1730Sstevel@tonic-gate */ 1740Sstevel@tonic-gate static time_t g_mechSetTime = (time_t)0; 1750Sstevel@tonic-gate static gss_OID_set_desc g_mechSet = { 0, NULL }; 1760Sstevel@tonic-gate static mutex_t g_mechSetLock; 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate OM_uint32 1800Sstevel@tonic-gate gss_indicate_mechs(minorStatus, mechSet) 1810Sstevel@tonic-gate OM_uint32 *minorStatus; 1820Sstevel@tonic-gate gss_OID_set *mechSet; 1830Sstevel@tonic-gate { 1840Sstevel@tonic-gate gss_mech_info mList; 1850Sstevel@tonic-gate char *fileName; 1860Sstevel@tonic-gate struct stat fileInfo; 1870Sstevel@tonic-gate int count, i, j; 1880Sstevel@tonic-gate gss_OID curItem; 1890Sstevel@tonic-gate 190*9698SPeter.Shoults@Sun.COM /* Initialize outputs. */ 191*9698SPeter.Shoults@Sun.COM 192*9698SPeter.Shoults@Sun.COM if (minorStatus != NULL) 193*9698SPeter.Shoults@Sun.COM *minorStatus = 0; 1940Sstevel@tonic-gate 195*9698SPeter.Shoults@Sun.COM if (mechSet != NULL) 196*9698SPeter.Shoults@Sun.COM *mechSet = GSS_C_NO_OID_SET; 1970Sstevel@tonic-gate 198*9698SPeter.Shoults@Sun.COM /* Validate arguments. */ 199*9698SPeter.Shoults@Sun.COM if (minorStatus == NULL || mechSet == NULL) 2000Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate fileName = MECH_CONF; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate /* 2050Sstevel@tonic-gate * If we have already computed the mechanisms supported and if it 2060Sstevel@tonic-gate * is still valid; make a copy and return to caller, 2070Sstevel@tonic-gate * otherwise build it first. 2080Sstevel@tonic-gate */ 2090Sstevel@tonic-gate if ((stat(fileName, &fileInfo) == 0 && 2100Sstevel@tonic-gate fileInfo.st_mtime > g_mechSetTime)) { 2110Sstevel@tonic-gate /* 2120Sstevel@tonic-gate * lock the mutex since we will be updating 2130Sstevel@tonic-gate * the mechList structure 2140Sstevel@tonic-gate * we need to keep the lock while we build the mechanism list 2150Sstevel@tonic-gate * since we are accessing parts of the mechList which could be 2160Sstevel@tonic-gate * modified. 2170Sstevel@tonic-gate */ 2180Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate /* 2210Sstevel@tonic-gate * this checks for the case when we need to re-construct the 2220Sstevel@tonic-gate * g_mechSet structure, but the mechanism list is upto date 2230Sstevel@tonic-gate * (because it has been read by someone calling 2240Sstevel@tonic-gate * __gss_get_mechanism) 2250Sstevel@tonic-gate */ 2260Sstevel@tonic-gate if (fileInfo.st_mtime > g_confFileModTime) 2270Sstevel@tonic-gate { 2280Sstevel@tonic-gate g_confFileModTime = fileInfo.st_mtime; 2290Sstevel@tonic-gate loadConfigFile(fileName); 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate /* 2330Sstevel@tonic-gate * we need to lock the mech set so that no one else will 2340Sstevel@tonic-gate * try to read it as we are re-creating it 2350Sstevel@tonic-gate */ 2360Sstevel@tonic-gate (void) mutex_lock(&g_mechSetLock); 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate /* if the oid list already exists we must free it first */ 2390Sstevel@tonic-gate if (g_mechSet.count != 0) { 2400Sstevel@tonic-gate for (i = 0; i < g_mechSet.count; i++) 2410Sstevel@tonic-gate free(g_mechSet.elements[i].elements); 2420Sstevel@tonic-gate free(g_mechSet.elements); 2430Sstevel@tonic-gate g_mechSet.elements = NULL; 2440Sstevel@tonic-gate g_mechSet.count = 0; 2450Sstevel@tonic-gate } 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate /* determine how many elements to have in the list */ 2480Sstevel@tonic-gate mList = g_mechList; 2490Sstevel@tonic-gate count = 0; 2500Sstevel@tonic-gate while (mList != NULL) { 2510Sstevel@tonic-gate count++; 2520Sstevel@tonic-gate mList = mList->next; 2530Sstevel@tonic-gate } 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* this should always be true, but.... */ 2560Sstevel@tonic-gate if (count > 0) { 2570Sstevel@tonic-gate g_mechSet.elements = 2580Sstevel@tonic-gate (gss_OID) calloc(count, sizeof (gss_OID_desc)); 2590Sstevel@tonic-gate if (g_mechSet.elements == NULL) { 2600Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 2610Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 2620Sstevel@tonic-gate return (GSS_S_FAILURE); 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate (void) memset(g_mechSet.elements, 0, 2660Sstevel@tonic-gate count * sizeof (gss_OID_desc)); 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate /* now copy each oid element */ 2690Sstevel@tonic-gate g_mechSet.count = count; 2700Sstevel@tonic-gate count = 0; 2710Sstevel@tonic-gate mList = g_mechList; 2720Sstevel@tonic-gate while (mList != NULL) { 2730Sstevel@tonic-gate curItem = &(g_mechSet.elements[count]); 2740Sstevel@tonic-gate curItem->elements = (void*) 2750Sstevel@tonic-gate malloc(mList->mech_type->length); 2760Sstevel@tonic-gate if (curItem->elements == NULL) { 2770Sstevel@tonic-gate /* 2780Sstevel@tonic-gate * this is nasty - we must delete the 2790Sstevel@tonic-gate * part of the array already copied 2800Sstevel@tonic-gate */ 2810Sstevel@tonic-gate for (i = 0; i < count; i++) { 2820Sstevel@tonic-gate free(g_mechSet.elements[i]. 2830Sstevel@tonic-gate elements); 2840Sstevel@tonic-gate } 2850Sstevel@tonic-gate free(g_mechSet.elements); 2860Sstevel@tonic-gate g_mechSet.count = 0; 2870Sstevel@tonic-gate g_mechSet.elements = NULL; 2880Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 2890Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 2900Sstevel@tonic-gate return (GSS_S_FAILURE); 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate g_OID_copy(curItem, mList->mech_type); 2930Sstevel@tonic-gate count++; 2940Sstevel@tonic-gate mList = mList->next; 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate g_mechSetTime = fileInfo.st_mtime; 2990Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 3000Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 3010Sstevel@tonic-gate } /* if g_mechSet is out of date or not initialized */ 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate /* 3040Sstevel@tonic-gate * the mech set is created and it is up to date 3050Sstevel@tonic-gate * so just copy it to caller 3060Sstevel@tonic-gate */ 3070Sstevel@tonic-gate if ((*mechSet = 3080Sstevel@tonic-gate (gss_OID_set) malloc(sizeof (gss_OID_set_desc))) == NULL) 3090Sstevel@tonic-gate { 3100Sstevel@tonic-gate return (GSS_S_FAILURE); 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate /* 3140Sstevel@tonic-gate * need to lock the g_mechSet in case someone tries to update it while 3150Sstevel@tonic-gate * I'm copying it. 3160Sstevel@tonic-gate */ 3170Sstevel@tonic-gate (void) mutex_lock(&g_mechSetLock); 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate /* allocate space for the oid structures */ 3200Sstevel@tonic-gate if (((*mechSet)->elements = 3210Sstevel@tonic-gate (void*) calloc(g_mechSet.count, sizeof (gss_OID_desc))) 3220Sstevel@tonic-gate == NULL) 3230Sstevel@tonic-gate { 3240Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 3250Sstevel@tonic-gate free(*mechSet); 3260Sstevel@tonic-gate *mechSet = NULL; 3270Sstevel@tonic-gate return (GSS_S_FAILURE); 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate /* now copy the oid structures */ 3310Sstevel@tonic-gate (void) memcpy((*mechSet)->elements, g_mechSet.elements, 3320Sstevel@tonic-gate g_mechSet.count * sizeof (gss_OID_desc)); 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate (*mechSet)->count = g_mechSet.count; 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate /* still need to copy each of the oid elements arrays */ 3370Sstevel@tonic-gate for (i = 0; i < (*mechSet)->count; i++) { 3380Sstevel@tonic-gate curItem = &((*mechSet)->elements[i]); 3390Sstevel@tonic-gate curItem->elements = 3400Sstevel@tonic-gate (void *) malloc(g_mechSet.elements[i].length); 3410Sstevel@tonic-gate if (curItem->elements == NULL) { 3420Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 3430Sstevel@tonic-gate /* 3440Sstevel@tonic-gate * must still free the allocated elements for 3450Sstevel@tonic-gate * each allocated gss_OID_desc 3460Sstevel@tonic-gate */ 3470Sstevel@tonic-gate for (j = 0; j < i; j++) { 3480Sstevel@tonic-gate free((*mechSet)->elements[j].elements); 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate free((*mechSet)->elements); 3510Sstevel@tonic-gate free(mechSet); 3520Sstevel@tonic-gate *mechSet = NULL; 3530Sstevel@tonic-gate return (GSS_S_FAILURE); 3540Sstevel@tonic-gate } 3550Sstevel@tonic-gate g_OID_copy(curItem, &g_mechSet.elements[i]); 3560Sstevel@tonic-gate } 3570Sstevel@tonic-gate (void) mutex_unlock(&g_mechSetLock); 3580Sstevel@tonic-gate return (GSS_S_COMPLETE); 3590Sstevel@tonic-gate } /* gss_indicate_mechs */ 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate /* 3620Sstevel@tonic-gate * this function has been added for use by modules that need to 3630Sstevel@tonic-gate * know what (if any) optional parameters are supplied in the 3640Sstevel@tonic-gate * config file (MECH_CONF). 3650Sstevel@tonic-gate * It will return the option string for a specified mechanism. 3660Sstevel@tonic-gate * caller is responsible for freeing the memory 3670Sstevel@tonic-gate */ 3680Sstevel@tonic-gate char * 3690Sstevel@tonic-gate __gss_get_modOptions(oid) 3700Sstevel@tonic-gate const gss_OID oid; 3710Sstevel@tonic-gate { 3720Sstevel@tonic-gate gss_mech_info aMech; 3730Sstevel@tonic-gate char *modOptions = NULL; 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate /* make sure we have fresh data */ 3760Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 3770Sstevel@tonic-gate updateMechList(); 3780Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate /* searching the list does not require a lock */ 3810Sstevel@tonic-gate if ((aMech = searchMechList(oid)) == NULL || 3820Sstevel@tonic-gate aMech->optionStr == NULL) { 3830Sstevel@tonic-gate return (NULL); 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate /* 3870Sstevel@tonic-gate * need to obtain a lock on this structure in case someone else 3880Sstevel@tonic-gate * will try to update it during the copy 3890Sstevel@tonic-gate */ 3900Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 3910Sstevel@tonic-gate if (aMech->optionStr) 3920Sstevel@tonic-gate modOptions = strdup(aMech->optionStr); 3930Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate return (modOptions); 3960Sstevel@tonic-gate } /* __gss_get_modOptions */ 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* 3990Sstevel@tonic-gate * this function has been added for use by gssd. 4000Sstevel@tonic-gate * It will return the kernel module name for a specified mechanism. 4010Sstevel@tonic-gate * caller is responsible for freeing the memory 4020Sstevel@tonic-gate */ 4030Sstevel@tonic-gate char * 4040Sstevel@tonic-gate __gss_get_kmodName(oid) 4050Sstevel@tonic-gate const gss_OID oid; 4060Sstevel@tonic-gate { 4070Sstevel@tonic-gate gss_mech_info aMech; 4080Sstevel@tonic-gate char *kmodName = NULL; 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate /* make sure we have fresh data */ 4110Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 4120Sstevel@tonic-gate updateMechList(); 4130Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate /* searching the list does not require a lock */ 4160Sstevel@tonic-gate if ((aMech = searchMechList(oid)) == NULL || aMech->kmodName == NULL) { 4170Sstevel@tonic-gate return (NULL); 4180Sstevel@tonic-gate } 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate /* 4210Sstevel@tonic-gate * need to obtain a lock on this structure in case someone else 4220Sstevel@tonic-gate * will try to update it during the copy 4230Sstevel@tonic-gate */ 4240Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 4250Sstevel@tonic-gate if (aMech->kmodName) 4260Sstevel@tonic-gate kmodName = strdup(aMech->kmodName); 4270Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate return (kmodName); 4300Sstevel@tonic-gate } /* __gss_get_kmodName */ 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate /* 4340Sstevel@tonic-gate * given a mechanism string return the mechanism oid 4350Sstevel@tonic-gate */ 4360Sstevel@tonic-gate OM_uint32 4370Sstevel@tonic-gate __gss_mech_to_oid(const char *mechStr, gss_OID* oid) 4380Sstevel@tonic-gate { 4390Sstevel@tonic-gate gss_mech_info aMech; 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate if (oid == NULL) 4420Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate *oid = GSS_C_NULL_OID; 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate if ((mechStr == NULL) || (strlen(mechStr) == 0) || 4470Sstevel@tonic-gate (strcasecmp(mechStr, M_DEFAULT) == 0)) 4480Sstevel@tonic-gate return (GSS_S_COMPLETE); 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate /* ensure we have fresh data */ 4510Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 4520Sstevel@tonic-gate updateMechList(); 4530Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate aMech = g_mechList; 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate /* no lock required - only looking at fields that are not updated */ 4580Sstevel@tonic-gate while (aMech != NULL) { 4590Sstevel@tonic-gate if ((aMech->mechNameStr) && 4600Sstevel@tonic-gate strcmp(aMech->mechNameStr, mechStr) == 0) { 4610Sstevel@tonic-gate *oid = aMech->mech_type; 4620Sstevel@tonic-gate return (GSS_S_COMPLETE); 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate aMech = aMech->next; 4650Sstevel@tonic-gate } 4660Sstevel@tonic-gate return (GSS_S_FAILURE); 4670Sstevel@tonic-gate } /* __gss_mech_to_oid */ 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate /* 4710Sstevel@tonic-gate * Given the mechanism oid, return the readable mechanism name 4720Sstevel@tonic-gate * associated with that oid from the mech config file 4730Sstevel@tonic-gate * (/etc/gss/mech). 4740Sstevel@tonic-gate */ 4750Sstevel@tonic-gate const char * 4760Sstevel@tonic-gate __gss_oid_to_mech(const gss_OID oid) 4770Sstevel@tonic-gate { 4780Sstevel@tonic-gate gss_mech_info aMech; 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate if (oid == GSS_C_NULL_OID) 4810Sstevel@tonic-gate return (M_DEFAULT); 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate /* ensure we have fresh data */ 4840Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 4850Sstevel@tonic-gate updateMechList(); 4860Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 4870Sstevel@tonic-gate 4880Sstevel@tonic-gate if ((aMech = searchMechList(oid)) == NULL) 4890Sstevel@tonic-gate return (NULL); 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate return (aMech->mechNameStr); 4920Sstevel@tonic-gate } /* __gss_oid_to_mech */ 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate /* 4960Sstevel@tonic-gate * return a list of mechanism strings supported 4970Sstevel@tonic-gate * upon return the array is terminated with a NULL entry 4980Sstevel@tonic-gate */ 4990Sstevel@tonic-gate OM_uint32 5000Sstevel@tonic-gate __gss_get_mechanisms(char *mechArray[], int arrayLen) 5010Sstevel@tonic-gate { 5020Sstevel@tonic-gate gss_mech_info aMech; 5030Sstevel@tonic-gate int i; 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate if (mechArray == NULL || arrayLen < 1) 5060Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate /* ensure we have fresh data */ 5090Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 5100Sstevel@tonic-gate updateMechList(); 5110Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate aMech = g_mechList; 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate /* no lock required - only looking at fields that are not updated */ 5160Sstevel@tonic-gate for (i = 1; i < arrayLen; i++) { 5170Sstevel@tonic-gate if (aMech != NULL) { 5180Sstevel@tonic-gate *mechArray = aMech->mechNameStr; 5190Sstevel@tonic-gate mechArray++; 5200Sstevel@tonic-gate aMech = aMech->next; 5210Sstevel@tonic-gate } else 5220Sstevel@tonic-gate break; 5230Sstevel@tonic-gate } 5240Sstevel@tonic-gate *mechArray = NULL; 5250Sstevel@tonic-gate return (GSS_S_COMPLETE); 5260Sstevel@tonic-gate } /* gss_get_mechanisms */ 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate /* 5300Sstevel@tonic-gate * determines if the mechList needs to be updated from file 5310Sstevel@tonic-gate * and performs the update. 5320Sstevel@tonic-gate * this functions must be called with a lock of g_mechListLock 5330Sstevel@tonic-gate */ 5340Sstevel@tonic-gate static void 5350Sstevel@tonic-gate updateMechList(void) 5360Sstevel@tonic-gate { 5370Sstevel@tonic-gate char *fileName; 5380Sstevel@tonic-gate struct stat fileInfo; 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate fileName = MECH_CONF; 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate /* check if mechList needs updating */ 5430Sstevel@tonic-gate if (stat(fileName, &fileInfo) == 0 && 5440Sstevel@tonic-gate (fileInfo.st_mtime > g_confFileModTime)) { 5450Sstevel@tonic-gate loadConfigFile(fileName); 5460Sstevel@tonic-gate g_confFileModTime = fileInfo.st_mtime; 5470Sstevel@tonic-gate } 5480Sstevel@tonic-gate } /* updateMechList */ 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate /* 5520Sstevel@tonic-gate * given the mechanism type, return the mechanism structure 5530Sstevel@tonic-gate * containing the mechanism library entry points. 5540Sstevel@tonic-gate * will return NULL if mech type is not found 5550Sstevel@tonic-gate * This function will also trigger the loading of the mechanism 5560Sstevel@tonic-gate * module if it has not been already loaded. 5570Sstevel@tonic-gate */ 5580Sstevel@tonic-gate gss_mechanism 5590Sstevel@tonic-gate __gss_get_mechanism(oid) 5600Sstevel@tonic-gate const gss_OID oid; 5610Sstevel@tonic-gate { 5620Sstevel@tonic-gate gss_mech_info aMech; 5630Sstevel@tonic-gate gss_mechanism (*sym)(const gss_OID); 5640Sstevel@tonic-gate void *dl; 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate /* check if the mechanism is already loaded */ 5670Sstevel@tonic-gate if ((aMech = searchMechList(oid)) != NULL && aMech->mech) { 5680Sstevel@tonic-gate return (aMech->mech); 5690Sstevel@tonic-gate } 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate /* 5720Sstevel@tonic-gate * might need to re-read the configuration file before loading 5730Sstevel@tonic-gate * the mechanism to ensure we have the latest info. 5740Sstevel@tonic-gate */ 5750Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 5760Sstevel@tonic-gate updateMechList(); 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate aMech = searchMechList(oid); 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate /* is the mechanism present in the list ? */ 5810Sstevel@tonic-gate if (aMech == NULL) { 5820Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 5830Sstevel@tonic-gate return ((gss_mechanism)NULL); 5840Sstevel@tonic-gate } 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate /* has another thread loaded the mech */ 5870Sstevel@tonic-gate if (aMech->mech) { 5880Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 5890Sstevel@tonic-gate return (aMech->mech); 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate /* we found the mechanism, but it is not loaded */ 5930Sstevel@tonic-gate if ((dl = dlopen(aMech->uLibName, RTLD_NOW)) == NULL) { 5940Sstevel@tonic-gate (void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n", 5950Sstevel@tonic-gate aMech->uLibName, dlerror()); 5960Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 5970Sstevel@tonic-gate return ((gss_mechanism)NULL); 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate if ((sym = (gss_mechanism (*)(const gss_OID))dlsym(dl, MECH_SYM)) 6010Sstevel@tonic-gate == NULL) { 6020Sstevel@tonic-gate (void) dlclose(dl); 6030Sstevel@tonic-gate (void) syslog(LOG_INFO, "unable to initialize mechanism" 6040Sstevel@tonic-gate " library [%s]\n", aMech->uLibName); 6050Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 6060Sstevel@tonic-gate return ((gss_mechanism)NULL); 6070Sstevel@tonic-gate } 6080Sstevel@tonic-gate 6090Sstevel@tonic-gate /* Call the symbol to get the mechanism table */ 6100Sstevel@tonic-gate aMech->mech = (*sym)(aMech->mech_type); 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate if (aMech->mech == NULL) { 6130Sstevel@tonic-gate (void) dlclose(dl); 6140Sstevel@tonic-gate (void) syslog(LOG_INFO, "unable to initialize mechanism" 6150Sstevel@tonic-gate " library [%s]\n", aMech->uLibName); 6160Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 6170Sstevel@tonic-gate return ((gss_mechanism)NULL); 6180Sstevel@tonic-gate } 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate aMech->dl_handle = dl; 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 6230Sstevel@tonic-gate return (aMech->mech); 6240Sstevel@tonic-gate } /* __gss_get_mechanism */ 6250Sstevel@tonic-gate 6260Sstevel@tonic-gate gss_mechanism_ext 6270Sstevel@tonic-gate __gss_get_mechanism_ext(oid) 6280Sstevel@tonic-gate const gss_OID oid; 6290Sstevel@tonic-gate { 6300Sstevel@tonic-gate gss_mech_info aMech; 6310Sstevel@tonic-gate gss_mechanism_ext mech_ext; 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate /* check if the mechanism is already loaded */ 6340Sstevel@tonic-gate if ((aMech = searchMechList(oid)) != NULL && aMech->mech_ext != NULL) 6350Sstevel@tonic-gate return (aMech->mech_ext); 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate if (__gss_get_mechanism(oid) == NULL) 6380Sstevel@tonic-gate return (NULL); 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate if (aMech->dl_handle == NULL) 6410Sstevel@tonic-gate return (NULL); 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate /* Load the gss_config_ext struct for this mech */ 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate mech_ext = (gss_mechanism_ext)malloc(sizeof (struct gss_config_ext)); 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate if (mech_ext == NULL) 6480Sstevel@tonic-gate return (NULL); 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate /* 6510Sstevel@tonic-gate * dlsym() the mech's 'method' functions for the extended APIs 6520Sstevel@tonic-gate * 6530Sstevel@tonic-gate * NOTE: Until the void *context argument is removed from the 6540Sstevel@tonic-gate * SPI method functions' signatures it will be necessary to have 6550Sstevel@tonic-gate * different function pointer typedefs and function names for 6560Sstevel@tonic-gate * the SPI methods than for the API. When this argument is 6570Sstevel@tonic-gate * removed it will be possible to rename gss_*_sfct to gss_*_fct 6580Sstevel@tonic-gate * and and gssspi_* to gss_*. 6590Sstevel@tonic-gate */ 6600Sstevel@tonic-gate mech_ext->gss_acquire_cred_with_password = 6610Sstevel@tonic-gate (gss_acquire_cred_with_password_sfct)dlsym(aMech->dl_handle, 6620Sstevel@tonic-gate "gssspi_acquire_cred_with_password"); 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate /* Set aMech->mech_ext */ 6650Sstevel@tonic-gate (void) mutex_lock(&g_mechListLock); 6660Sstevel@tonic-gate 6670Sstevel@tonic-gate if (aMech->mech_ext == NULL) 6680Sstevel@tonic-gate aMech->mech_ext = mech_ext; 6690Sstevel@tonic-gate else 6700Sstevel@tonic-gate free(mech_ext); /* we raced and lost; don't leak */ 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate (void) mutex_unlock(&g_mechListLock); 6730Sstevel@tonic-gate 6740Sstevel@tonic-gate return (aMech->mech_ext); 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate } /* __gss_get_mechanism_ext */ 6770Sstevel@tonic-gate 6780Sstevel@tonic-gate 6790Sstevel@tonic-gate /* 6800Sstevel@tonic-gate * this routine is used for searching the list of mechanism data. 6810Sstevel@tonic-gate * it needs not be mutex protected because we only add new structures 6820Sstevel@tonic-gate * from the end and they are fully initialized before being added. 6830Sstevel@tonic-gate */ 6840Sstevel@tonic-gate static gss_mech_info searchMechList(oid) 6850Sstevel@tonic-gate const gss_OID oid; 6860Sstevel@tonic-gate { 6870Sstevel@tonic-gate gss_mech_info aMech = g_mechList; 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate /* if oid is null -> then get default which is the first in the list */ 6900Sstevel@tonic-gate if (oid == GSS_C_NULL_OID) 6910Sstevel@tonic-gate return (aMech); 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate while (aMech != NULL) { 6940Sstevel@tonic-gate if (g_OID_equal(aMech->mech_type, oid)) 6950Sstevel@tonic-gate return (aMech); 6960Sstevel@tonic-gate aMech = aMech->next; 6970Sstevel@tonic-gate } 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate /* none found */ 7000Sstevel@tonic-gate return ((gss_mech_info) NULL); 7010Sstevel@tonic-gate } /* searchMechList */ 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate /* 7050Sstevel@tonic-gate * loads the configuration file 7060Sstevel@tonic-gate * this is called while having a mutex lock on the mechanism list 7070Sstevel@tonic-gate * entries for libraries that have been loaded can't be modified 7080Sstevel@tonic-gate * mechNameStr and mech_type fields are not updated during updates 7090Sstevel@tonic-gate */ 7100Sstevel@tonic-gate static void loadConfigFile(fileName) 7110Sstevel@tonic-gate const char *fileName; 7120Sstevel@tonic-gate { 7130Sstevel@tonic-gate char buffer[BUFSIZ], *oidStr, *oid, *sharedLib, *kernMod, *endp; 7140Sstevel@tonic-gate char *modOptions; 7150Sstevel@tonic-gate char sharedPath[sizeof (MECH_LIB_PREFIX) + BUFSIZ]; 7160Sstevel@tonic-gate char *tmpStr; 7170Sstevel@tonic-gate FILE *confFile; 7180Sstevel@tonic-gate gss_OID mechOid; 7190Sstevel@tonic-gate gss_mech_info aMech, tmp; 7200Sstevel@tonic-gate OM_uint32 minor; 7210Sstevel@tonic-gate gss_buffer_desc oidBuf; 7220Sstevel@tonic-gate 7231914Scasper if ((confFile = fopen(fileName, "rF")) == NULL) { 7240Sstevel@tonic-gate return; 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate (void) memset(buffer, 0, sizeof (buffer)); 7280Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, confFile) != NULL) { 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate /* ignore lines beginning with # */ 7310Sstevel@tonic-gate if (*buffer == '#') 7320Sstevel@tonic-gate continue; 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate /* 7350Sstevel@tonic-gate * find the first white-space character after 7360Sstevel@tonic-gate * the mechanism name 7370Sstevel@tonic-gate */ 7380Sstevel@tonic-gate oidStr = buffer; 7390Sstevel@tonic-gate for (oid = buffer; *oid && !isspace(*oid); oid++); 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate /* Now find the first non-white-space character */ 7420Sstevel@tonic-gate if (*oid) { 7430Sstevel@tonic-gate *oid = '\0'; 7440Sstevel@tonic-gate oid++; 7450Sstevel@tonic-gate while (*oid && isspace(*oid)) 7460Sstevel@tonic-gate oid++; 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate /* 7500Sstevel@tonic-gate * If that's all, then this is a corrupt entry. Skip it. 7510Sstevel@tonic-gate */ 7520Sstevel@tonic-gate if (! *oid) 7530Sstevel@tonic-gate continue; 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate /* Find the end of the oid and make sure it is NULL-ended */ 7560Sstevel@tonic-gate for (endp = oid; *endp && !isspace(*endp); endp++) 7570Sstevel@tonic-gate ; 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate if (*endp) { 7600Sstevel@tonic-gate *endp = '\0'; 7610Sstevel@tonic-gate } 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate /* 7640Sstevel@tonic-gate * check if an entry for this oid already exists 7650Sstevel@tonic-gate * if it does, and the library is already loaded then 7660Sstevel@tonic-gate * we can't modify it, so skip it 7670Sstevel@tonic-gate */ 7680Sstevel@tonic-gate oidBuf.value = (void *)oid; 7690Sstevel@tonic-gate oidBuf.length = strlen(oid); 7700Sstevel@tonic-gate if (generic_gss_str_to_oid(&minor, &oidBuf, &mechOid) 7710Sstevel@tonic-gate != GSS_S_COMPLETE) { 7720Sstevel@tonic-gate (void) syslog(LOG_INFO, "invalid mechanism oid" 7730Sstevel@tonic-gate " [%s] in configuration file", oid); 7740Sstevel@tonic-gate continue; 7750Sstevel@tonic-gate } 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate aMech = searchMechList(mechOid); 7780Sstevel@tonic-gate if (aMech && aMech->mech) { 7790Sstevel@tonic-gate free(mechOid->elements); 7800Sstevel@tonic-gate free(mechOid); 7810Sstevel@tonic-gate continue; 7820Sstevel@tonic-gate } 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate /* Find the start of the shared lib name */ 7850Sstevel@tonic-gate for (sharedLib = endp+1; *sharedLib && isspace(*sharedLib); 7860Sstevel@tonic-gate sharedLib++) 7870Sstevel@tonic-gate ; 7880Sstevel@tonic-gate 7890Sstevel@tonic-gate /* 7900Sstevel@tonic-gate * If that's all, then this is a corrupt entry. Skip it. 7910Sstevel@tonic-gate */ 7920Sstevel@tonic-gate if (! *sharedLib) { 7930Sstevel@tonic-gate free(mechOid->elements); 7940Sstevel@tonic-gate free(mechOid); 7950Sstevel@tonic-gate continue; 7960Sstevel@tonic-gate } 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate /* 7990Sstevel@tonic-gate * Find the end of the shared lib name and make sure it is 8000Sstevel@tonic-gate * NULL-terminated. 8010Sstevel@tonic-gate */ 8020Sstevel@tonic-gate for (endp = sharedLib; *endp && !isspace(*endp); endp++) 8030Sstevel@tonic-gate ; 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate if (*endp) { 8060Sstevel@tonic-gate *endp = '\0'; 8070Sstevel@tonic-gate } 8080Sstevel@tonic-gate 8090Sstevel@tonic-gate /* Find the start of the optional kernel module lib name */ 8100Sstevel@tonic-gate for (kernMod = endp+1; *kernMod && isspace(*kernMod); 8110Sstevel@tonic-gate kernMod++) 8120Sstevel@tonic-gate ; 8130Sstevel@tonic-gate 8140Sstevel@tonic-gate /* 8150Sstevel@tonic-gate * If this item starts with a bracket "[", then 8160Sstevel@tonic-gate * it is not a kernel module, but is a list of 8170Sstevel@tonic-gate * options for the user module to parse later. 8180Sstevel@tonic-gate */ 8190Sstevel@tonic-gate if (*kernMod && *kernMod != '[') { 8200Sstevel@tonic-gate /* 8210Sstevel@tonic-gate * Find the end of the shared lib name and make sure 8220Sstevel@tonic-gate * it is NULL-terminated. 8230Sstevel@tonic-gate */ 8240Sstevel@tonic-gate for (endp = kernMod; *endp && !isspace(*endp); endp++) 8250Sstevel@tonic-gate ; 8260Sstevel@tonic-gate 8270Sstevel@tonic-gate if (*endp) { 8280Sstevel@tonic-gate *endp = '\0'; 8290Sstevel@tonic-gate } 8300Sstevel@tonic-gate } else 8310Sstevel@tonic-gate kernMod = NULL; 8320Sstevel@tonic-gate 8330Sstevel@tonic-gate /* Find the start of the optional module options list */ 8340Sstevel@tonic-gate for (modOptions = endp+1; *modOptions && isspace(*modOptions); 8350Sstevel@tonic-gate modOptions++); 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate if (*modOptions == '[') { 8380Sstevel@tonic-gate /* move past the opening bracket */ 8390Sstevel@tonic-gate for (modOptions = modOptions+1; 8400Sstevel@tonic-gate *modOptions && isspace(*modOptions); 8410Sstevel@tonic-gate modOptions++); 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate /* Find the closing bracket */ 8440Sstevel@tonic-gate for (endp = modOptions; 8450Sstevel@tonic-gate *endp && *endp != ']'; endp++); 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate if (endp) 8480Sstevel@tonic-gate *endp = '\0'; 8490Sstevel@tonic-gate 8500Sstevel@tonic-gate } else { 8510Sstevel@tonic-gate modOptions = NULL; 8520Sstevel@tonic-gate } 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate (void) strcpy(sharedPath, MECH_LIB_PREFIX); 8550Sstevel@tonic-gate (void) strcat(sharedPath, sharedLib); 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate /* 8580Sstevel@tonic-gate * are we creating a new mechanism entry or 8590Sstevel@tonic-gate * just modifying existing (non loaded) mechanism entry 8600Sstevel@tonic-gate */ 8610Sstevel@tonic-gate if (aMech) { 8620Sstevel@tonic-gate /* 8630Sstevel@tonic-gate * delete any old values and set new 8640Sstevel@tonic-gate * mechNameStr and mech_type are not modified 8650Sstevel@tonic-gate */ 8660Sstevel@tonic-gate if (aMech->kmodName) { 8670Sstevel@tonic-gate free(aMech->kmodName); 8680Sstevel@tonic-gate aMech->kmodName = NULL; 8690Sstevel@tonic-gate } 8700Sstevel@tonic-gate 8710Sstevel@tonic-gate if (aMech->optionStr) { 8720Sstevel@tonic-gate free(aMech->optionStr); 8730Sstevel@tonic-gate aMech->optionStr = NULL; 8740Sstevel@tonic-gate } 8750Sstevel@tonic-gate 8760Sstevel@tonic-gate if ((tmpStr = strdup(sharedPath)) != NULL) { 8770Sstevel@tonic-gate if (aMech->uLibName) 8780Sstevel@tonic-gate free(aMech->uLibName); 8790Sstevel@tonic-gate aMech->uLibName = tmpStr; 8800Sstevel@tonic-gate } 8810Sstevel@tonic-gate 8820Sstevel@tonic-gate if (kernMod) /* this is an optional parameter */ 8830Sstevel@tonic-gate aMech->kmodName = strdup(kernMod); 8840Sstevel@tonic-gate 8850Sstevel@tonic-gate if (modOptions) /* optional module options */ 8860Sstevel@tonic-gate aMech->optionStr = strdup(modOptions); 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate /* the oid is already set */ 8890Sstevel@tonic-gate free(mechOid->elements); 8900Sstevel@tonic-gate free(mechOid); 8910Sstevel@tonic-gate continue; 8920Sstevel@tonic-gate } 8930Sstevel@tonic-gate 8940Sstevel@tonic-gate /* adding a new entry */ 8950Sstevel@tonic-gate aMech = malloc(sizeof (struct gss_mech_config)); 8960Sstevel@tonic-gate if (aMech == NULL) { 8970Sstevel@tonic-gate free(mechOid->elements); 8980Sstevel@tonic-gate free(mechOid); 8990Sstevel@tonic-gate continue; 9000Sstevel@tonic-gate } 9010Sstevel@tonic-gate (void) memset(aMech, 0, sizeof (struct gss_mech_config)); 9020Sstevel@tonic-gate aMech->mech_type = mechOid; 9030Sstevel@tonic-gate aMech->uLibName = strdup(sharedPath); 9040Sstevel@tonic-gate aMech->mechNameStr = strdup(oidStr); 9050Sstevel@tonic-gate 9060Sstevel@tonic-gate /* check if any memory allocations failed - bad news */ 9070Sstevel@tonic-gate if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) { 9080Sstevel@tonic-gate if (aMech->uLibName) 9090Sstevel@tonic-gate free(aMech->uLibName); 9100Sstevel@tonic-gate if (aMech->mechNameStr) 9110Sstevel@tonic-gate free(aMech->mechNameStr); 9120Sstevel@tonic-gate free(mechOid->elements); 9130Sstevel@tonic-gate free(mechOid); 9140Sstevel@tonic-gate free(aMech); 9150Sstevel@tonic-gate continue; 9160Sstevel@tonic-gate } 9170Sstevel@tonic-gate if (kernMod) /* this is an optional parameter */ 9180Sstevel@tonic-gate aMech->kmodName = strdup(kernMod); 9190Sstevel@tonic-gate 9200Sstevel@tonic-gate if (modOptions) 9210Sstevel@tonic-gate aMech->optionStr = strdup(modOptions); 9220Sstevel@tonic-gate /* 9230Sstevel@tonic-gate * add the new entry to the end of the list - make sure 9240Sstevel@tonic-gate * that only complete entries are added because other 9250Sstevel@tonic-gate * threads might currently be searching the list. 9260Sstevel@tonic-gate */ 9270Sstevel@tonic-gate tmp = g_mechListTail; 9280Sstevel@tonic-gate g_mechListTail = aMech; 9290Sstevel@tonic-gate 9300Sstevel@tonic-gate if (tmp != NULL) 9310Sstevel@tonic-gate tmp->next = aMech; 9320Sstevel@tonic-gate 9330Sstevel@tonic-gate if (g_mechList == NULL) 9340Sstevel@tonic-gate g_mechList = aMech; 9350Sstevel@tonic-gate } /* while */ 9360Sstevel@tonic-gate (void) fclose(confFile); 9370Sstevel@tonic-gate } /* loadConfigFile */ 938