xref: /onnv-gate/usr/src/lib/libgss/g_initialize.c (revision 13132:9615cdbf7b70)
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
gss_release_oid(minor_status,oid)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
gss_indicate_mechs(minorStatus,mechSet)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 *
__gss_get_modOptions(oid)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 *
__gss_get_kmodName(oid)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
__gss_mech_to_oid(const char * mechStr,gss_OID * oid)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 *
__gss_oid_to_mech(const gss_OID oid)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
__gss_get_mechanisms(char * mechArray[],int arrayLen)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
updateMechList(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
__gss_get_mechanism(oid)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
__gss_get_mechanism_ext(oid)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  */
searchMechList(oid)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  */
loadConfigFile(fileName)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