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