xref: /illumos-gate/usr/src/lib/libgss/g_initialize.c (revision 6a634c9d)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5004388ebScasper  * Common Development and Distribution License (the "License").
6004388ebScasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*5e01956fSGlenn Barry  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  * This file contains functions to initialize the gssapi library and
277c478bd9Sstevel@tonic-gate  * load mechanism libraries.
287c478bd9Sstevel@tonic-gate  *
297c478bd9Sstevel@tonic-gate  * It also contain functions requiring direct access to the mechanism's
307c478bd9Sstevel@tonic-gate  * list (gss_inidicate_mechs and gss_release_oid) as well as support
317c478bd9Sstevel@tonic-gate  * functions which translate the mechanism strings to oids and vise versa.
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * The mechanism libraries are loaded on demand.  This is triggered
347c478bd9Sstevel@tonic-gate  * through the get_mechanism function call.
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  * Updates to the mechList are performed with the following restrictions:
377c478bd9Sstevel@tonic-gate  *	- once a library is loaded, none of the fields are updated
387c478bd9Sstevel@tonic-gate  *	- existing entiries for non-loaded mechs, will have the
397c478bd9Sstevel@tonic-gate  *		library and kernel module names updated only
407c478bd9Sstevel@tonic-gate  *		(i.e. the mech oid and mech name will not be updated)
417c478bd9Sstevel@tonic-gate  */
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #include <mechglueP.h>
44*5e01956fSGlenn Barry #include "gssapiP_generic.h"
457c478bd9Sstevel@tonic-gate #include <stdio.h>
467c478bd9Sstevel@tonic-gate #include <syslog.h>
477c478bd9Sstevel@tonic-gate #include <stdlib.h>
487c478bd9Sstevel@tonic-gate #include <string.h>
497c478bd9Sstevel@tonic-gate #include <sys/stat.h>
507c478bd9Sstevel@tonic-gate #include <ctype.h>
517c478bd9Sstevel@tonic-gate #include <errno.h>
527c478bd9Sstevel@tonic-gate #include <synch.h>
537c478bd9Sstevel@tonic-gate #include <dlfcn.h>
547c478bd9Sstevel@tonic-gate #include <libintl.h>
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN
587c478bd9Sstevel@tonic-gate #error TEXT_DOMAIN not defined
597c478bd9Sstevel@tonic-gate #endif
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #define	MECH_CONF "/etc/gss/mech"
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX1	"/usr/lib/"
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * This #ifdef mess figures out if we are to be compiled into
677c478bd9Sstevel@tonic-gate  * a sparcv9/lp64 binary for the purposes of figuring the absolute location
687c478bd9Sstevel@tonic-gate  * of gss-api mechanism modules.
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate #ifdef	_LP64
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #ifdef	__sparc
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX2	"sparcv9/"
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate #elif defined(__amd64)
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX2	"amd64/"
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate #else	/* __sparc */
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate you need to define where under /usr the LP64 libraries live for this platform
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate #endif	/* __sparc */
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate #else	/* _LP64 */
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX2	""
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #define	MECH_LIB_DIR		"gss/"
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX	MECH_LIB_PREFIX1 MECH_LIB_PREFIX2 MECH_LIB_DIR
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate #ifndef	MECH_SYM
987c478bd9Sstevel@tonic-gate #define	MECH_SYM "gss_mech_initialize"
997c478bd9Sstevel@tonic-gate #endif
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #define	M_DEFAULT	"default"
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /* Local functions */
1047c478bd9Sstevel@tonic-gate static gss_mech_info searchMechList(const gss_OID);
1057c478bd9Sstevel@tonic-gate static void loadConfigFile(const char *);
1067c478bd9Sstevel@tonic-gate static void updateMechList(void);
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate /*
1107c478bd9Sstevel@tonic-gate  * list of mechanism libraries and their entry points.
1117c478bd9Sstevel@tonic-gate  * the list also maintains state of the mech libraries (loaded or not).
1127c478bd9Sstevel@tonic-gate  */
1137c478bd9Sstevel@tonic-gate static gss_mech_info g_mechList = NULL;
1147c478bd9Sstevel@tonic-gate static gss_mech_info g_mechListTail = NULL;
1157c478bd9Sstevel@tonic-gate static mutex_t g_mechListLock;
1167c478bd9Sstevel@tonic-gate static time_t g_confFileModTime = (time_t)0;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * function used to reclaim the memory used by a gss_OID structure.
1207c478bd9Sstevel@tonic-gate  * This routine requires direct access to the mechList.
1217c478bd9Sstevel@tonic-gate  */
1227c478bd9Sstevel@tonic-gate OM_uint32
gss_release_oid(minor_status,oid)1237c478bd9Sstevel@tonic-gate gss_release_oid(minor_status, oid)
1247c478bd9Sstevel@tonic-gate OM_uint32 *minor_status;
1257c478bd9Sstevel@tonic-gate gss_OID *oid;
1267c478bd9Sstevel@tonic-gate {
1277c478bd9Sstevel@tonic-gate 	OM_uint32 major;
1287c478bd9Sstevel@tonic-gate 	gss_mech_info aMech = g_mechList;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	if (minor_status == NULL)
1317c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	*minor_status = 0;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	while (aMech != NULL) {
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 		/*
1387c478bd9Sstevel@tonic-gate 		 * look through the loaded mechanism libraries for
1397c478bd9Sstevel@tonic-gate 		 * gss_internal_release_oid until one returns success.
1407c478bd9Sstevel@tonic-gate 		 * gss_internal_release_oid will only return success when
1417c478bd9Sstevel@tonic-gate 		 * the OID was recognized as an internal mechanism OID. if no
1427c478bd9Sstevel@tonic-gate 		 * mechanisms recognize the OID, then call the generic version.
1437c478bd9Sstevel@tonic-gate 		 */
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 		/*
1467c478bd9Sstevel@tonic-gate 		 * we can walk the mechanism list without a mutex, because we
1477c478bd9Sstevel@tonic-gate 		 * are only looking at fields which once read will never change.
1487c478bd9Sstevel@tonic-gate 		 * Mechanism entries are always added to the end, and as
1497c478bd9Sstevel@tonic-gate 		 * complete entries.
1507c478bd9Sstevel@tonic-gate 		 */
1517c478bd9Sstevel@tonic-gate 		if (aMech->mech && aMech->mech->gss_internal_release_oid) {
1527c478bd9Sstevel@tonic-gate 			major = aMech->mech->gss_internal_release_oid(
1537c478bd9Sstevel@tonic-gate 					aMech->mech->context,
1547c478bd9Sstevel@tonic-gate 					minor_status, oid);
1557c478bd9Sstevel@tonic-gate 			if (major == GSS_S_COMPLETE)
1567c478bd9Sstevel@tonic-gate 				return (GSS_S_COMPLETE);
157*5e01956fSGlenn Barry 			map_error(minor_status, aMech->mech);
1587c478bd9Sstevel@tonic-gate 		}
1597c478bd9Sstevel@tonic-gate 		aMech = aMech->next;
1607c478bd9Sstevel@tonic-gate 	} /* while */
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	return (generic_gss_release_oid(minor_status, oid));
1637c478bd9Sstevel@tonic-gate } /* gss_release_oid */
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate /*
1677c478bd9Sstevel@tonic-gate  * this function will return an oid set indicating available mechanisms.
1687c478bd9Sstevel@tonic-gate  * The set returned is based on configuration file entries and
1697c478bd9Sstevel@tonic-gate  * NOT on the loaded mechanisms.  This function does not check if any
1707c478bd9Sstevel@tonic-gate  * of these can actually be loaded.
1717c478bd9Sstevel@tonic-gate  * This routine needs direct access to the mechanism list.
1727c478bd9Sstevel@tonic-gate  * To avoid reading the configuration file each call, we will save a
1737c478bd9Sstevel@tonic-gate  * a mech oid set, and only update it once the file has changed.
1747c478bd9Sstevel@tonic-gate  */
1757c478bd9Sstevel@tonic-gate static time_t g_mechSetTime = (time_t)0;
1767c478bd9Sstevel@tonic-gate static gss_OID_set_desc g_mechSet = { 0, NULL };
1777c478bd9Sstevel@tonic-gate static mutex_t g_mechSetLock;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate OM_uint32
gss_indicate_mechs(minorStatus,mechSet)1817c478bd9Sstevel@tonic-gate gss_indicate_mechs(minorStatus, mechSet)
1827c478bd9Sstevel@tonic-gate OM_uint32 *minorStatus;
1837c478bd9Sstevel@tonic-gate gss_OID_set *mechSet;
1847c478bd9Sstevel@tonic-gate {
1857c478bd9Sstevel@tonic-gate 	gss_mech_info mList;
1867c478bd9Sstevel@tonic-gate 	char *fileName;
1877c478bd9Sstevel@tonic-gate 	struct stat fileInfo;
1887c478bd9Sstevel@tonic-gate 	int count, i, j;
1897c478bd9Sstevel@tonic-gate 	gss_OID curItem;
1907c478bd9Sstevel@tonic-gate 
191503a2b89SPeter Shoults 	/* Initialize outputs. */
1927c478bd9Sstevel@tonic-gate 
193503a2b89SPeter Shoults 	if (minorStatus != NULL)
194503a2b89SPeter Shoults 		*minorStatus = 0;
1957c478bd9Sstevel@tonic-gate 
196503a2b89SPeter Shoults 	if (mechSet != NULL)
197503a2b89SPeter Shoults 		*mechSet = GSS_C_NO_OID_SET;
1987c478bd9Sstevel@tonic-gate 
199503a2b89SPeter Shoults 	/* Validate arguments. */
200503a2b89SPeter Shoults 	if (minorStatus == NULL || mechSet == NULL)
2017c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	fileName = MECH_CONF;
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	/*
2067c478bd9Sstevel@tonic-gate 	 * If we have already computed the mechanisms supported and if it
2077c478bd9Sstevel@tonic-gate 	 * is still valid; make a copy and return to caller,
2087c478bd9Sstevel@tonic-gate 	 * otherwise build it first.
2097c478bd9Sstevel@tonic-gate 	 */
2107c478bd9Sstevel@tonic-gate 	if ((stat(fileName, &fileInfo) == 0 &&
2117c478bd9Sstevel@tonic-gate 		fileInfo.st_mtime > g_mechSetTime)) {
2127c478bd9Sstevel@tonic-gate 		/*
2137c478bd9Sstevel@tonic-gate 		 * lock the mutex since we will be updating
2147c478bd9Sstevel@tonic-gate 		 * the mechList structure
2157c478bd9Sstevel@tonic-gate 		 * we need to keep the lock while we build the mechanism list
2167c478bd9Sstevel@tonic-gate 		 * since we are accessing parts of the mechList which could be
2177c478bd9Sstevel@tonic-gate 		 * modified.
2187c478bd9Sstevel@tonic-gate 		 */
2197c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&g_mechListLock);
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 		/*
2227c478bd9Sstevel@tonic-gate 		 * this checks for the case when we need to re-construct the
2237c478bd9Sstevel@tonic-gate 		 * g_mechSet structure, but the mechanism list is upto date
2247c478bd9Sstevel@tonic-gate 		 * (because it has been read by someone calling
2257c478bd9Sstevel@tonic-gate 		 * __gss_get_mechanism)
2267c478bd9Sstevel@tonic-gate 		 */
2277c478bd9Sstevel@tonic-gate 		if (fileInfo.st_mtime > g_confFileModTime)
2287c478bd9Sstevel@tonic-gate 		{
2297c478bd9Sstevel@tonic-gate 			g_confFileModTime = fileInfo.st_mtime;
2307c478bd9Sstevel@tonic-gate 			loadConfigFile(fileName);
2317c478bd9Sstevel@tonic-gate 		}
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 		/*
2347c478bd9Sstevel@tonic-gate 		 * we need to lock the mech set so that no one else will
2357c478bd9Sstevel@tonic-gate 		 * try to read it as we are re-creating it
2367c478bd9Sstevel@tonic-gate 		 */
2377c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&g_mechSetLock);
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 		/* if the oid list already exists we must free it first */
2407c478bd9Sstevel@tonic-gate 		if (g_mechSet.count != 0) {
2417c478bd9Sstevel@tonic-gate 			for (i = 0; i < g_mechSet.count; i++)
2427c478bd9Sstevel@tonic-gate 				free(g_mechSet.elements[i].elements);
2437c478bd9Sstevel@tonic-gate 			free(g_mechSet.elements);
2447c478bd9Sstevel@tonic-gate 			g_mechSet.elements = NULL;
2457c478bd9Sstevel@tonic-gate 			g_mechSet.count = 0;
2467c478bd9Sstevel@tonic-gate 		}
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 		/* determine how many elements to have in the list */
2497c478bd9Sstevel@tonic-gate 		mList = g_mechList;
2507c478bd9Sstevel@tonic-gate 		count = 0;
2517c478bd9Sstevel@tonic-gate 		while (mList != NULL) {
2527c478bd9Sstevel@tonic-gate 			count++;
2537c478bd9Sstevel@tonic-gate 			mList = mList->next;
2547c478bd9Sstevel@tonic-gate 		}
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 		/* this should always be true, but.... */
2577c478bd9Sstevel@tonic-gate 		if (count > 0) {
2587c478bd9Sstevel@tonic-gate 			g_mechSet.elements =
2597c478bd9Sstevel@tonic-gate 				(gss_OID) calloc(count, sizeof (gss_OID_desc));
2607c478bd9Sstevel@tonic-gate 			if (g_mechSet.elements == NULL) {
2617c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&g_mechSetLock);
2627c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&g_mechListLock);
2637c478bd9Sstevel@tonic-gate 				return (GSS_S_FAILURE);
2647c478bd9Sstevel@tonic-gate 			}
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 			(void) memset(g_mechSet.elements, 0,
2677c478bd9Sstevel@tonic-gate 				count * sizeof (gss_OID_desc));
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 			/* now copy each oid element */
2707c478bd9Sstevel@tonic-gate 			g_mechSet.count = count;
2717c478bd9Sstevel@tonic-gate 			count = 0;
2727c478bd9Sstevel@tonic-gate 			mList = g_mechList;
2737c478bd9Sstevel@tonic-gate 			while (mList != NULL) {
2747c478bd9Sstevel@tonic-gate 				curItem = &(g_mechSet.elements[count]);
2757c478bd9Sstevel@tonic-gate 				curItem->elements = (void*)
2767c478bd9Sstevel@tonic-gate 					malloc(mList->mech_type->length);
2777c478bd9Sstevel@tonic-gate 				if (curItem->elements == NULL) {
2787c478bd9Sstevel@tonic-gate 					/*
2797c478bd9Sstevel@tonic-gate 					 * this is nasty - we must delete the
2807c478bd9Sstevel@tonic-gate 					 * part of the array already copied
2817c478bd9Sstevel@tonic-gate 					 */
2827c478bd9Sstevel@tonic-gate 					for (i = 0; i < count; i++) {
2837c478bd9Sstevel@tonic-gate 						free(g_mechSet.elements[i].
2847c478bd9Sstevel@tonic-gate 							elements);
2857c478bd9Sstevel@tonic-gate 					}
2867c478bd9Sstevel@tonic-gate 					free(g_mechSet.elements);
2877c478bd9Sstevel@tonic-gate 					g_mechSet.count = 0;
2887c478bd9Sstevel@tonic-gate 					g_mechSet.elements = NULL;
2897c478bd9Sstevel@tonic-gate 					(void) mutex_unlock(&g_mechSetLock);
2907c478bd9Sstevel@tonic-gate 					(void) mutex_unlock(&g_mechListLock);
2917c478bd9Sstevel@tonic-gate 					return (GSS_S_FAILURE);
2927c478bd9Sstevel@tonic-gate 				}
2937c478bd9Sstevel@tonic-gate 				g_OID_copy(curItem, mList->mech_type);
2947c478bd9Sstevel@tonic-gate 				count++;
2957c478bd9Sstevel@tonic-gate 				mList = mList->next;
2967c478bd9Sstevel@tonic-gate 			}
2977c478bd9Sstevel@tonic-gate 		}
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 		g_mechSetTime = fileInfo.st_mtime;
3007c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechSetLock);
3017c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
3027c478bd9Sstevel@tonic-gate 	} /* if g_mechSet is out of date or not initialized */
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	/*
3057c478bd9Sstevel@tonic-gate 	 * the mech set is created and it is up to date
3067c478bd9Sstevel@tonic-gate 	 * so just copy it to caller
3077c478bd9Sstevel@tonic-gate 	 */
3087c478bd9Sstevel@tonic-gate 	if ((*mechSet =
3097c478bd9Sstevel@tonic-gate 		(gss_OID_set) malloc(sizeof (gss_OID_set_desc))) == NULL)
3107c478bd9Sstevel@tonic-gate 	{
3117c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	/*
3157c478bd9Sstevel@tonic-gate 	 * need to lock the g_mechSet in case someone tries to update it while
3167c478bd9Sstevel@tonic-gate 	 * I'm copying it.
3177c478bd9Sstevel@tonic-gate 	 */
3187c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechSetLock);
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	/* allocate space for the oid structures */
3217c478bd9Sstevel@tonic-gate 	if (((*mechSet)->elements =
3227c478bd9Sstevel@tonic-gate 		(void*) calloc(g_mechSet.count, sizeof (gss_OID_desc)))
3237c478bd9Sstevel@tonic-gate 		== NULL)
3247c478bd9Sstevel@tonic-gate 	{
3257c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechSetLock);
3267c478bd9Sstevel@tonic-gate 		free(*mechSet);
3277c478bd9Sstevel@tonic-gate 		*mechSet = NULL;
3287c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
3297c478bd9Sstevel@tonic-gate 	}
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	/* now copy the oid structures */
3327c478bd9Sstevel@tonic-gate 	(void) memcpy((*mechSet)->elements, g_mechSet.elements,
3337c478bd9Sstevel@tonic-gate 		g_mechSet.count * sizeof (gss_OID_desc));
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	(*mechSet)->count = g_mechSet.count;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	/* still need to copy each of the oid elements arrays */
3387c478bd9Sstevel@tonic-gate 	for (i = 0; i < (*mechSet)->count; i++) {
3397c478bd9Sstevel@tonic-gate 		curItem = &((*mechSet)->elements[i]);
3407c478bd9Sstevel@tonic-gate 		curItem->elements =
3417c478bd9Sstevel@tonic-gate 			(void *) malloc(g_mechSet.elements[i].length);
3427c478bd9Sstevel@tonic-gate 		if (curItem->elements == NULL) {
3437c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&g_mechSetLock);
3447c478bd9Sstevel@tonic-gate 			/*
3457c478bd9Sstevel@tonic-gate 			 * must still free the allocated elements for
3467c478bd9Sstevel@tonic-gate 			 * each allocated gss_OID_desc
3477c478bd9Sstevel@tonic-gate 			 */
3487c478bd9Sstevel@tonic-gate 			for (j = 0; j < i; j++) {
3497c478bd9Sstevel@tonic-gate 				free((*mechSet)->elements[j].elements);
3507c478bd9Sstevel@tonic-gate 			}
3517c478bd9Sstevel@tonic-gate 			free((*mechSet)->elements);
3527c478bd9Sstevel@tonic-gate 			free(mechSet);
3537c478bd9Sstevel@tonic-gate 			*mechSet = NULL;
3547c478bd9Sstevel@tonic-gate 			return (GSS_S_FAILURE);
3557c478bd9Sstevel@tonic-gate 		}
3567c478bd9Sstevel@tonic-gate 		g_OID_copy(curItem, &g_mechSet.elements[i]);
3577c478bd9Sstevel@tonic-gate 	}
3587c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechSetLock);
3597c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
3607c478bd9Sstevel@tonic-gate } /* gss_indicate_mechs */
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate /*
3637c478bd9Sstevel@tonic-gate  * this function has been added for use by modules that need to
3647c478bd9Sstevel@tonic-gate  * know what (if any) optional parameters are supplied in the
3657c478bd9Sstevel@tonic-gate  * config file (MECH_CONF).
3667c478bd9Sstevel@tonic-gate  * It will return the option string for a specified mechanism.
3677c478bd9Sstevel@tonic-gate  * caller is responsible for freeing the memory
3687c478bd9Sstevel@tonic-gate  */
3697c478bd9Sstevel@tonic-gate char *
__gss_get_modOptions(oid)3707c478bd9Sstevel@tonic-gate __gss_get_modOptions(oid)
3717c478bd9Sstevel@tonic-gate const gss_OID oid;
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
3747c478bd9Sstevel@tonic-gate 	char *modOptions = NULL;
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	/* make sure we have fresh data */
3777c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
3787c478bd9Sstevel@tonic-gate 	updateMechList();
3797c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	/* searching the list does not require a lock */
3827c478bd9Sstevel@tonic-gate 	if ((aMech = searchMechList(oid)) == NULL ||
3837c478bd9Sstevel@tonic-gate 		aMech->optionStr == NULL) {
3847c478bd9Sstevel@tonic-gate 		return (NULL);
3857c478bd9Sstevel@tonic-gate 	}
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	/*
3887c478bd9Sstevel@tonic-gate 	 * need to obtain a lock on this structure in case someone else
3897c478bd9Sstevel@tonic-gate 	 * will try to update it during the copy
3907c478bd9Sstevel@tonic-gate 	 */
3917c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
3927c478bd9Sstevel@tonic-gate 	if (aMech->optionStr)
3937c478bd9Sstevel@tonic-gate 		modOptions = strdup(aMech->optionStr);
3947c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	return (modOptions);
3977c478bd9Sstevel@tonic-gate } /* __gss_get_modOptions */
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate /*
4007c478bd9Sstevel@tonic-gate  * this function has been added for use by gssd.
4017c478bd9Sstevel@tonic-gate  * It will return the kernel module name for a specified mechanism.
4027c478bd9Sstevel@tonic-gate  * caller is responsible for freeing the memory
4037c478bd9Sstevel@tonic-gate  */
4047c478bd9Sstevel@tonic-gate char *
__gss_get_kmodName(oid)4057c478bd9Sstevel@tonic-gate __gss_get_kmodName(oid)
4067c478bd9Sstevel@tonic-gate const gss_OID oid;
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
4097c478bd9Sstevel@tonic-gate 	char *kmodName = NULL;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	/* make sure we have fresh data */
4127c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
4137c478bd9Sstevel@tonic-gate 	updateMechList();
4147c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	/* searching the list does not require a lock */
4177c478bd9Sstevel@tonic-gate 	if ((aMech = searchMechList(oid)) == NULL || aMech->kmodName == NULL) {
4187c478bd9Sstevel@tonic-gate 		return (NULL);
4197c478bd9Sstevel@tonic-gate 	}
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	/*
4227c478bd9Sstevel@tonic-gate 	 * need to obtain a lock on this structure in case someone else
4237c478bd9Sstevel@tonic-gate 	 * will try to update it during the copy
4247c478bd9Sstevel@tonic-gate 	 */
4257c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
4267c478bd9Sstevel@tonic-gate 	if (aMech->kmodName)
4277c478bd9Sstevel@tonic-gate 		kmodName = strdup(aMech->kmodName);
4287c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	return (kmodName);
4317c478bd9Sstevel@tonic-gate } /* __gss_get_kmodName */
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate /*
4357c478bd9Sstevel@tonic-gate  * given a mechanism string return the mechanism oid
4367c478bd9Sstevel@tonic-gate  */
4377c478bd9Sstevel@tonic-gate OM_uint32
__gss_mech_to_oid(const char * mechStr,gss_OID * oid)4387c478bd9Sstevel@tonic-gate __gss_mech_to_oid(const char *mechStr, gss_OID* oid)
4397c478bd9Sstevel@tonic-gate {
4407c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	if (oid == NULL)
4437c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	*oid = GSS_C_NULL_OID;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	if ((mechStr == NULL) || (strlen(mechStr) == 0) ||
4487c478bd9Sstevel@tonic-gate 		(strcasecmp(mechStr, M_DEFAULT) == 0))
4497c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	/* ensure we have fresh data */
4527c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
4537c478bd9Sstevel@tonic-gate 	updateMechList();
4547c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	aMech = g_mechList;
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	/* no lock required - only looking at fields that are not updated */
4597c478bd9Sstevel@tonic-gate 	while (aMech != NULL) {
4607c478bd9Sstevel@tonic-gate 		if ((aMech->mechNameStr) &&
4617c478bd9Sstevel@tonic-gate 			strcmp(aMech->mechNameStr, mechStr) == 0) {
4627c478bd9Sstevel@tonic-gate 			*oid = aMech->mech_type;
4637c478bd9Sstevel@tonic-gate 			return (GSS_S_COMPLETE);
4647c478bd9Sstevel@tonic-gate 		}
4657c478bd9Sstevel@tonic-gate 		aMech = aMech->next;
4667c478bd9Sstevel@tonic-gate 	}
4677c478bd9Sstevel@tonic-gate 	return (GSS_S_FAILURE);
4687c478bd9Sstevel@tonic-gate } /* __gss_mech_to_oid */
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate /*
4727c478bd9Sstevel@tonic-gate  * Given the mechanism oid, return the readable mechanism name
4737c478bd9Sstevel@tonic-gate  * associated with that oid from the mech config file
4747c478bd9Sstevel@tonic-gate  * (/etc/gss/mech).
4757c478bd9Sstevel@tonic-gate  */
4767c478bd9Sstevel@tonic-gate const char *
__gss_oid_to_mech(const gss_OID oid)4777c478bd9Sstevel@tonic-gate __gss_oid_to_mech(const gss_OID oid)
4787c478bd9Sstevel@tonic-gate {
4797c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	if (oid == GSS_C_NULL_OID)
4827c478bd9Sstevel@tonic-gate 		return (M_DEFAULT);
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	/* ensure we have fresh data */
4857c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
4867c478bd9Sstevel@tonic-gate 	updateMechList();
4877c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	if ((aMech = searchMechList(oid)) == NULL)
4907c478bd9Sstevel@tonic-gate 		return (NULL);
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	return (aMech->mechNameStr);
4937c478bd9Sstevel@tonic-gate } /* __gss_oid_to_mech */
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate /*
4977c478bd9Sstevel@tonic-gate  * return a list of mechanism strings supported
4987c478bd9Sstevel@tonic-gate  * upon return the array is terminated with a NULL entry
4997c478bd9Sstevel@tonic-gate  */
5007c478bd9Sstevel@tonic-gate OM_uint32
__gss_get_mechanisms(char * mechArray[],int arrayLen)5017c478bd9Sstevel@tonic-gate __gss_get_mechanisms(char *mechArray[], int arrayLen)
5027c478bd9Sstevel@tonic-gate {
5037c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
5047c478bd9Sstevel@tonic-gate 	int i;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	if (mechArray == NULL || arrayLen < 1)
5077c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	/* ensure we have fresh data */
5107c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
5117c478bd9Sstevel@tonic-gate 	updateMechList();
5127c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	aMech = g_mechList;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	/* no lock required - only looking at fields that are not updated */
5177c478bd9Sstevel@tonic-gate 	for (i = 1; i < arrayLen; i++) {
5187c478bd9Sstevel@tonic-gate 		if (aMech != NULL) {
5197c478bd9Sstevel@tonic-gate 			*mechArray = aMech->mechNameStr;
5207c478bd9Sstevel@tonic-gate 			mechArray++;
5217c478bd9Sstevel@tonic-gate 			aMech = aMech->next;
5227c478bd9Sstevel@tonic-gate 		} else
5237c478bd9Sstevel@tonic-gate 			break;
5247c478bd9Sstevel@tonic-gate 	}
5257c478bd9Sstevel@tonic-gate 	*mechArray = NULL;
5267c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
5277c478bd9Sstevel@tonic-gate } /* gss_get_mechanisms */
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate /*
5317c478bd9Sstevel@tonic-gate  * determines if the mechList needs to be updated from file
5327c478bd9Sstevel@tonic-gate  * and performs the update.
5337c478bd9Sstevel@tonic-gate  * this functions must be called with a lock of g_mechListLock
5347c478bd9Sstevel@tonic-gate  */
5357c478bd9Sstevel@tonic-gate static void
updateMechList(void)5367c478bd9Sstevel@tonic-gate updateMechList(void)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate 	char *fileName;
5397c478bd9Sstevel@tonic-gate 	struct stat fileInfo;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	fileName = MECH_CONF;
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	/* check if mechList needs updating */
5447c478bd9Sstevel@tonic-gate 	if (stat(fileName, &fileInfo) == 0 &&
5457c478bd9Sstevel@tonic-gate 		(fileInfo.st_mtime > g_confFileModTime)) {
5467c478bd9Sstevel@tonic-gate 		loadConfigFile(fileName);
5477c478bd9Sstevel@tonic-gate 		g_confFileModTime = fileInfo.st_mtime;
5487c478bd9Sstevel@tonic-gate 	}
5497c478bd9Sstevel@tonic-gate } /* updateMechList */
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate /*
5537c478bd9Sstevel@tonic-gate  * given the mechanism type, return the mechanism structure
5547c478bd9Sstevel@tonic-gate  * containing the mechanism library entry points.
5557c478bd9Sstevel@tonic-gate  * will return NULL if mech type is not found
5567c478bd9Sstevel@tonic-gate  * This function will also trigger the loading of the mechanism
5577c478bd9Sstevel@tonic-gate  * module if it has not been already loaded.
5587c478bd9Sstevel@tonic-gate  */
5597c478bd9Sstevel@tonic-gate gss_mechanism
__gss_get_mechanism(oid)5607c478bd9Sstevel@tonic-gate __gss_get_mechanism(oid)
5617c478bd9Sstevel@tonic-gate const gss_OID oid;
5627c478bd9Sstevel@tonic-gate {
5637c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
5647c478bd9Sstevel@tonic-gate 	gss_mechanism (*sym)(const gss_OID);
5657c478bd9Sstevel@tonic-gate 	void *dl;
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 	/* check if the mechanism is already loaded */
5687c478bd9Sstevel@tonic-gate 	if ((aMech = searchMechList(oid)) != NULL && aMech->mech) {
5697c478bd9Sstevel@tonic-gate 		return (aMech->mech);
5707c478bd9Sstevel@tonic-gate 	}
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	/*
5737c478bd9Sstevel@tonic-gate 	 * might need to re-read the configuration file before loading
5747c478bd9Sstevel@tonic-gate 	 * the mechanism to ensure we have the latest info.
5757c478bd9Sstevel@tonic-gate 	 */
5767c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
5777c478bd9Sstevel@tonic-gate 	updateMechList();
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	aMech = searchMechList(oid);
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	/* is the mechanism present in the list ? */
5827c478bd9Sstevel@tonic-gate 	if (aMech == NULL) {
5837c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
5847c478bd9Sstevel@tonic-gate 		return ((gss_mechanism)NULL);
5857c478bd9Sstevel@tonic-gate 	}
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	/* has another thread loaded the mech */
5887c478bd9Sstevel@tonic-gate 	if (aMech->mech) {
5897c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
5907c478bd9Sstevel@tonic-gate 		return (aMech->mech);
5917c478bd9Sstevel@tonic-gate 	}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	/* we found the mechanism, but it is not loaded */
5947c478bd9Sstevel@tonic-gate 	if ((dl = dlopen(aMech->uLibName, RTLD_NOW)) == NULL) {
5957c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n",
5967c478bd9Sstevel@tonic-gate 				aMech->uLibName, dlerror());
5977c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
5987c478bd9Sstevel@tonic-gate 		return ((gss_mechanism)NULL);
5997c478bd9Sstevel@tonic-gate 	}
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	if ((sym = (gss_mechanism (*)(const gss_OID))dlsym(dl, MECH_SYM))
6027c478bd9Sstevel@tonic-gate 			== NULL) {
6037c478bd9Sstevel@tonic-gate 		(void) dlclose(dl);
6047c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_INFO, "unable to initialize mechanism"
6057c478bd9Sstevel@tonic-gate 				" library [%s]\n", aMech->uLibName);
6067c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
6077c478bd9Sstevel@tonic-gate 		return ((gss_mechanism)NULL);
6087c478bd9Sstevel@tonic-gate 	}
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	/* Call the symbol to get the mechanism table */
6117c478bd9Sstevel@tonic-gate 	aMech->mech = (*sym)(aMech->mech_type);
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	if (aMech->mech == NULL) {
6147c478bd9Sstevel@tonic-gate 		(void) dlclose(dl);
6157c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_INFO, "unable to initialize mechanism"
6167c478bd9Sstevel@tonic-gate 				" library [%s]\n", aMech->uLibName);
6177c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
6187c478bd9Sstevel@tonic-gate 		return ((gss_mechanism)NULL);
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	aMech->dl_handle = dl;
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
6247c478bd9Sstevel@tonic-gate 	return (aMech->mech);
6257c478bd9Sstevel@tonic-gate } /* __gss_get_mechanism */
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate gss_mechanism_ext
__gss_get_mechanism_ext(oid)6287c478bd9Sstevel@tonic-gate __gss_get_mechanism_ext(oid)
6297c478bd9Sstevel@tonic-gate const gss_OID oid;
6307c478bd9Sstevel@tonic-gate {
6317c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
6327c478bd9Sstevel@tonic-gate 	gss_mechanism_ext mech_ext;
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	/* check if the mechanism is already loaded */
6357c478bd9Sstevel@tonic-gate 	if ((aMech = searchMechList(oid)) != NULL && aMech->mech_ext != NULL)
6367c478bd9Sstevel@tonic-gate 		return (aMech->mech_ext);
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	if (__gss_get_mechanism(oid) == NULL)
6397c478bd9Sstevel@tonic-gate 		return (NULL);
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	if (aMech->dl_handle == NULL)
6427c478bd9Sstevel@tonic-gate 		return (NULL);
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	/* Load the gss_config_ext struct for this mech */
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	mech_ext = (gss_mechanism_ext)malloc(sizeof (struct gss_config_ext));
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 	if (mech_ext == NULL)
6497c478bd9Sstevel@tonic-gate 		return (NULL);
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	/*
6527c478bd9Sstevel@tonic-gate 	 * dlsym() the mech's 'method' functions for the extended APIs
6537c478bd9Sstevel@tonic-gate 	 *
6547c478bd9Sstevel@tonic-gate 	 * NOTE:  Until the void *context argument is removed from the
6557c478bd9Sstevel@tonic-gate 	 * SPI method functions' signatures it will be necessary to have
6567c478bd9Sstevel@tonic-gate 	 * different function pointer typedefs and function names for
6577c478bd9Sstevel@tonic-gate 	 * the SPI methods than for the API.  When this argument is
6587c478bd9Sstevel@tonic-gate 	 * removed it will be possible to rename gss_*_sfct to gss_*_fct
6597c478bd9Sstevel@tonic-gate 	 * and and gssspi_* to gss_*.
6607c478bd9Sstevel@tonic-gate 	 */
6617c478bd9Sstevel@tonic-gate 	mech_ext->gss_acquire_cred_with_password =
6627c478bd9Sstevel@tonic-gate 		(gss_acquire_cred_with_password_sfct)dlsym(aMech->dl_handle,
6637c478bd9Sstevel@tonic-gate 			"gssspi_acquire_cred_with_password");
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	/* Set aMech->mech_ext */
6667c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 	if (aMech->mech_ext == NULL)
6697c478bd9Sstevel@tonic-gate 		aMech->mech_ext = mech_ext;
6707c478bd9Sstevel@tonic-gate 	else
6717c478bd9Sstevel@tonic-gate 		free(mech_ext);	/* we raced and lost; don't leak */
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 	return (aMech->mech_ext);
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate } /* __gss_get_mechanism_ext */
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate /*
6817c478bd9Sstevel@tonic-gate  * this routine is used for searching the list of mechanism data.
6827c478bd9Sstevel@tonic-gate  * it needs not be mutex protected because we only add new structures
6837c478bd9Sstevel@tonic-gate  * from the end and they are fully initialized before being added.
6847c478bd9Sstevel@tonic-gate  */
searchMechList(oid)6857c478bd9Sstevel@tonic-gate static gss_mech_info searchMechList(oid)
6867c478bd9Sstevel@tonic-gate const gss_OID oid;
6877c478bd9Sstevel@tonic-gate {
6887c478bd9Sstevel@tonic-gate 	gss_mech_info aMech = g_mechList;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	/* if oid is null -> then get default which is the first in the list */
6917c478bd9Sstevel@tonic-gate 	if (oid == GSS_C_NULL_OID)
6927c478bd9Sstevel@tonic-gate 		return (aMech);
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	while (aMech != NULL) {
6957c478bd9Sstevel@tonic-gate 		if (g_OID_equal(aMech->mech_type, oid))
6967c478bd9Sstevel@tonic-gate 			return (aMech);
6977c478bd9Sstevel@tonic-gate 		aMech = aMech->next;
6987c478bd9Sstevel@tonic-gate 	}
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	/* none found */
7017c478bd9Sstevel@tonic-gate 	return ((gss_mech_info) NULL);
7027c478bd9Sstevel@tonic-gate } /* searchMechList */
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate /*
7067c478bd9Sstevel@tonic-gate  * loads the configuration file
7077c478bd9Sstevel@tonic-gate  * this is called while having a mutex lock on the mechanism list
7087c478bd9Sstevel@tonic-gate  * entries for libraries that have been loaded can't be modified
7097c478bd9Sstevel@tonic-gate  * mechNameStr and mech_type fields are not updated during updates
7107c478bd9Sstevel@tonic-gate  */
loadConfigFile(fileName)7117c478bd9Sstevel@tonic-gate static void loadConfigFile(fileName)
7127c478bd9Sstevel@tonic-gate const char *fileName;
7137c478bd9Sstevel@tonic-gate {
7147c478bd9Sstevel@tonic-gate 	char buffer[BUFSIZ], *oidStr, *oid, *sharedLib, *kernMod, *endp;
7157c478bd9Sstevel@tonic-gate 	char *modOptions;
7167c478bd9Sstevel@tonic-gate 	char sharedPath[sizeof (MECH_LIB_PREFIX) + BUFSIZ];
7177c478bd9Sstevel@tonic-gate 	char *tmpStr;
7187c478bd9Sstevel@tonic-gate 	FILE *confFile;
7197c478bd9Sstevel@tonic-gate 	gss_OID mechOid;
7207c478bd9Sstevel@tonic-gate 	gss_mech_info aMech, tmp;
7217c478bd9Sstevel@tonic-gate 	OM_uint32 minor;
7227c478bd9Sstevel@tonic-gate 	gss_buffer_desc oidBuf;
7237c478bd9Sstevel@tonic-gate 
724004388ebScasper 	if ((confFile = fopen(fileName, "rF")) == NULL) {
7257c478bd9Sstevel@tonic-gate 		return;
7267c478bd9Sstevel@tonic-gate 	}
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 	(void) memset(buffer, 0, sizeof (buffer));
7297c478bd9Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, confFile) != NULL) {
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 		/* ignore lines beginning with # */
7327c478bd9Sstevel@tonic-gate 		if (*buffer == '#')
7337c478bd9Sstevel@tonic-gate 			continue;
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 		/*
7367c478bd9Sstevel@tonic-gate 		 * find the first white-space character after
7377c478bd9Sstevel@tonic-gate 		 * the mechanism name
7387c478bd9Sstevel@tonic-gate 		 */
7397c478bd9Sstevel@tonic-gate 		oidStr = buffer;
7407c478bd9Sstevel@tonic-gate 		for (oid = buffer; *oid && !isspace(*oid); oid++);
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 		/* Now find the first non-white-space character */
7437c478bd9Sstevel@tonic-gate 		if (*oid) {
7447c478bd9Sstevel@tonic-gate 			*oid = '\0';
7457c478bd9Sstevel@tonic-gate 			oid++;
7467c478bd9Sstevel@tonic-gate 			while (*oid && isspace(*oid))
7477c478bd9Sstevel@tonic-gate 				oid++;
7487c478bd9Sstevel@tonic-gate 		}
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 		/*
7517c478bd9Sstevel@tonic-gate 		 * If that's all, then this is a corrupt entry. Skip it.
7527c478bd9Sstevel@tonic-gate 		 */
7537c478bd9Sstevel@tonic-gate 		if (! *oid)
7547c478bd9Sstevel@tonic-gate 			continue;
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 		/* Find the end of the oid and make sure it is NULL-ended */
7577c478bd9Sstevel@tonic-gate 		for (endp = oid; *endp && !isspace(*endp); endp++)
7587c478bd9Sstevel@tonic-gate 			;
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 		if (*endp) {
7617c478bd9Sstevel@tonic-gate 			*endp = '\0';
7627c478bd9Sstevel@tonic-gate 		}
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate 		/*
7657c478bd9Sstevel@tonic-gate 		 * check if an entry for this oid already exists
7667c478bd9Sstevel@tonic-gate 		 * if it does, and the library is already loaded then
7677c478bd9Sstevel@tonic-gate 		 * we can't modify it, so skip it
7687c478bd9Sstevel@tonic-gate 		 */
7697c478bd9Sstevel@tonic-gate 		oidBuf.value = (void *)oid;
7707c478bd9Sstevel@tonic-gate 		oidBuf.length = strlen(oid);
7717c478bd9Sstevel@tonic-gate 		if (generic_gss_str_to_oid(&minor, &oidBuf, &mechOid)
7727c478bd9Sstevel@tonic-gate 			!= GSS_S_COMPLETE) {
7737c478bd9Sstevel@tonic-gate 			(void) syslog(LOG_INFO, "invalid mechanism oid"
7747c478bd9Sstevel@tonic-gate 					" [%s] in configuration file", oid);
7757c478bd9Sstevel@tonic-gate 			continue;
7767c478bd9Sstevel@tonic-gate 		}
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 		aMech = searchMechList(mechOid);
7797c478bd9Sstevel@tonic-gate 		if (aMech && aMech->mech) {
7807c478bd9Sstevel@tonic-gate 			free(mechOid->elements);
7817c478bd9Sstevel@tonic-gate 			free(mechOid);
7827c478bd9Sstevel@tonic-gate 			continue;
7837c478bd9Sstevel@tonic-gate 		}
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 		/* Find the start of the shared lib name */
7867c478bd9Sstevel@tonic-gate 		for (sharedLib = endp+1; *sharedLib && isspace(*sharedLib);
7877c478bd9Sstevel@tonic-gate 			sharedLib++)
7887c478bd9Sstevel@tonic-gate 			;
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 		/*
7917c478bd9Sstevel@tonic-gate 		 * If that's all, then this is a corrupt entry. Skip it.
7927c478bd9Sstevel@tonic-gate 		 */
7937c478bd9Sstevel@tonic-gate 		if (! *sharedLib) {
7947c478bd9Sstevel@tonic-gate 			free(mechOid->elements);
7957c478bd9Sstevel@tonic-gate 			free(mechOid);
7967c478bd9Sstevel@tonic-gate 			continue;
7977c478bd9Sstevel@tonic-gate 		}
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 		/*
8007c478bd9Sstevel@tonic-gate 		 * Find the end of the shared lib name and make sure it is
8017c478bd9Sstevel@tonic-gate 		 *  NULL-terminated.
8027c478bd9Sstevel@tonic-gate 		 */
8037c478bd9Sstevel@tonic-gate 		for (endp = sharedLib; *endp && !isspace(*endp); endp++)
8047c478bd9Sstevel@tonic-gate 			;
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 		if (*endp) {
8077c478bd9Sstevel@tonic-gate 			*endp = '\0';
8087c478bd9Sstevel@tonic-gate 		}
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 		/* Find the start of the optional kernel module lib name */
8117c478bd9Sstevel@tonic-gate 		for (kernMod = endp+1; *kernMod && isspace(*kernMod);
8127c478bd9Sstevel@tonic-gate 			kernMod++)
8137c478bd9Sstevel@tonic-gate 			;
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 		/*
8167c478bd9Sstevel@tonic-gate 		 * If this item starts with a bracket "[", then
8177c478bd9Sstevel@tonic-gate 		 * it is not a kernel module, but is a list of
8187c478bd9Sstevel@tonic-gate 		 * options for the user module to parse later.
8197c478bd9Sstevel@tonic-gate 		 */
8207c478bd9Sstevel@tonic-gate 		if (*kernMod && *kernMod != '[') {
8217c478bd9Sstevel@tonic-gate 			/*
8227c478bd9Sstevel@tonic-gate 			 * Find the end of the shared lib name and make sure
8237c478bd9Sstevel@tonic-gate 			 * it is NULL-terminated.
8247c478bd9Sstevel@tonic-gate 			 */
8257c478bd9Sstevel@tonic-gate 			for (endp = kernMod; *endp && !isspace(*endp); endp++)
8267c478bd9Sstevel@tonic-gate 				;
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 			if (*endp) {
8297c478bd9Sstevel@tonic-gate 				*endp = '\0';
8307c478bd9Sstevel@tonic-gate 			}
8317c478bd9Sstevel@tonic-gate 		} else
8327c478bd9Sstevel@tonic-gate 			kernMod = NULL;
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 		/* Find the start of the optional module options list */
8357c478bd9Sstevel@tonic-gate 		for (modOptions = endp+1; *modOptions && isspace(*modOptions);
8367c478bd9Sstevel@tonic-gate 			modOptions++);
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 		if (*modOptions == '[')  {
8397c478bd9Sstevel@tonic-gate 			/* move past the opening bracket */
8407c478bd9Sstevel@tonic-gate 			for (modOptions = modOptions+1;
8417c478bd9Sstevel@tonic-gate 			    *modOptions && isspace(*modOptions);
8427c478bd9Sstevel@tonic-gate 			    modOptions++);
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 			/* Find the closing bracket */
8457c478bd9Sstevel@tonic-gate 			for (endp = modOptions;
8467c478bd9Sstevel@tonic-gate 				*endp && *endp != ']'; endp++);
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 			if (endp)
8497c478bd9Sstevel@tonic-gate 				*endp = '\0';
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 		} else {
8527c478bd9Sstevel@tonic-gate 			modOptions = NULL;
8537c478bd9Sstevel@tonic-gate 		}
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 		(void) strcpy(sharedPath, MECH_LIB_PREFIX);
8567c478bd9Sstevel@tonic-gate 		(void) strcat(sharedPath, sharedLib);
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 		/*
8597c478bd9Sstevel@tonic-gate 		 * are we creating a new mechanism entry or
8607c478bd9Sstevel@tonic-gate 		 * just modifying existing (non loaded) mechanism entry
8617c478bd9Sstevel@tonic-gate 		 */
8627c478bd9Sstevel@tonic-gate 		if (aMech) {
8637c478bd9Sstevel@tonic-gate 			/*
8647c478bd9Sstevel@tonic-gate 			 * delete any old values and set new
8657c478bd9Sstevel@tonic-gate 			 * mechNameStr and mech_type are not modified
8667c478bd9Sstevel@tonic-gate 			 */
8677c478bd9Sstevel@tonic-gate 			if (aMech->kmodName) {
8687c478bd9Sstevel@tonic-gate 				free(aMech->kmodName);
8697c478bd9Sstevel@tonic-gate 				aMech->kmodName = NULL;
8707c478bd9Sstevel@tonic-gate 			}
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 			if (aMech->optionStr) {
8737c478bd9Sstevel@tonic-gate 				free(aMech->optionStr);
8747c478bd9Sstevel@tonic-gate 				aMech->optionStr = NULL;
8757c478bd9Sstevel@tonic-gate 			}
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 			if ((tmpStr = strdup(sharedPath)) != NULL) {
8787c478bd9Sstevel@tonic-gate 				if (aMech->uLibName)
8797c478bd9Sstevel@tonic-gate 					free(aMech->uLibName);
8807c478bd9Sstevel@tonic-gate 				aMech->uLibName = tmpStr;
8817c478bd9Sstevel@tonic-gate 			}
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 			if (kernMod) /* this is an optional parameter */
8847c478bd9Sstevel@tonic-gate 				aMech->kmodName = strdup(kernMod);
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 			if (modOptions) /* optional module options */
8877c478bd9Sstevel@tonic-gate 				aMech->optionStr = strdup(modOptions);
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate 			/* the oid is already set */
8907c478bd9Sstevel@tonic-gate 			free(mechOid->elements);
8917c478bd9Sstevel@tonic-gate 			free(mechOid);
8927c478bd9Sstevel@tonic-gate 			continue;
8937c478bd9Sstevel@tonic-gate 		}
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 		/* adding a new entry */
8967c478bd9Sstevel@tonic-gate 		aMech = malloc(sizeof (struct gss_mech_config));
8977c478bd9Sstevel@tonic-gate 		if (aMech == NULL) {
8987c478bd9Sstevel@tonic-gate 			free(mechOid->elements);
8997c478bd9Sstevel@tonic-gate 			free(mechOid);
9007c478bd9Sstevel@tonic-gate 			continue;
9017c478bd9Sstevel@tonic-gate 		}
9027c478bd9Sstevel@tonic-gate 		(void) memset(aMech, 0, sizeof (struct gss_mech_config));
9037c478bd9Sstevel@tonic-gate 		aMech->mech_type = mechOid;
9047c478bd9Sstevel@tonic-gate 		aMech->uLibName = strdup(sharedPath);
9057c478bd9Sstevel@tonic-gate 		aMech->mechNameStr = strdup(oidStr);
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 		/* check if any memory allocations failed - bad news */
9087c478bd9Sstevel@tonic-gate 		if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) {
9097c478bd9Sstevel@tonic-gate 			if (aMech->uLibName)
9107c478bd9Sstevel@tonic-gate 				free(aMech->uLibName);
9117c478bd9Sstevel@tonic-gate 			if (aMech->mechNameStr)
9127c478bd9Sstevel@tonic-gate 				free(aMech->mechNameStr);
9137c478bd9Sstevel@tonic-gate 			free(mechOid->elements);
9147c478bd9Sstevel@tonic-gate 			free(mechOid);
9157c478bd9Sstevel@tonic-gate 			free(aMech);
9167c478bd9Sstevel@tonic-gate 			continue;
9177c478bd9Sstevel@tonic-gate 		}
9187c478bd9Sstevel@tonic-gate 		if (kernMod)	/* this is an optional parameter */
9197c478bd9Sstevel@tonic-gate 			aMech->kmodName = strdup(kernMod);
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 		if (modOptions)
9227c478bd9Sstevel@tonic-gate 			aMech->optionStr = strdup(modOptions);
9237c478bd9Sstevel@tonic-gate 		/*
9247c478bd9Sstevel@tonic-gate 		 * add the new entry to the end of the list - make sure
9257c478bd9Sstevel@tonic-gate 		 * that only complete entries are added because other
9267c478bd9Sstevel@tonic-gate 		 * threads might currently be searching the list.
9277c478bd9Sstevel@tonic-gate 		 */
9287c478bd9Sstevel@tonic-gate 		tmp = g_mechListTail;
9297c478bd9Sstevel@tonic-gate 		g_mechListTail = aMech;
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 		if (tmp != NULL)
9327c478bd9Sstevel@tonic-gate 			tmp->next = aMech;
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 		if (g_mechList == NULL)
9357c478bd9Sstevel@tonic-gate 			g_mechList = aMech;
9367c478bd9Sstevel@tonic-gate 	} /* while */
9377c478bd9Sstevel@tonic-gate 	(void) fclose(confFile);
9387c478bd9Sstevel@tonic-gate } /* loadConfigFile */
939