xref: /illumos-gate/usr/src/lib/libgss/g_initialize.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * This file contains functions to initialize the gssapi library and
31*7c478bd9Sstevel@tonic-gate  * load mechanism libraries.
32*7c478bd9Sstevel@tonic-gate  *
33*7c478bd9Sstevel@tonic-gate  * It also contain functions requiring direct access to the mechanism's
34*7c478bd9Sstevel@tonic-gate  * list (gss_inidicate_mechs and gss_release_oid) as well as support
35*7c478bd9Sstevel@tonic-gate  * functions which translate the mechanism strings to oids and vise versa.
36*7c478bd9Sstevel@tonic-gate  *
37*7c478bd9Sstevel@tonic-gate  * The mechanism libraries are loaded on demand.  This is triggered
38*7c478bd9Sstevel@tonic-gate  * through the get_mechanism function call.
39*7c478bd9Sstevel@tonic-gate  *
40*7c478bd9Sstevel@tonic-gate  * Updates to the mechList are performed with the following restrictions:
41*7c478bd9Sstevel@tonic-gate  *	- once a library is loaded, none of the fields are updated
42*7c478bd9Sstevel@tonic-gate  *	- existing entiries for non-loaded mechs, will have the
43*7c478bd9Sstevel@tonic-gate  *		library and kernel module names updated only
44*7c478bd9Sstevel@tonic-gate  *		(i.e. the mech oid and mech name will not be updated)
45*7c478bd9Sstevel@tonic-gate  */
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate #include <mechglueP.h>
48*7c478bd9Sstevel@tonic-gate #include <stdio.h>
49*7c478bd9Sstevel@tonic-gate #include <syslog.h>
50*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
51*7c478bd9Sstevel@tonic-gate #include <string.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
53*7c478bd9Sstevel@tonic-gate #include <ctype.h>
54*7c478bd9Sstevel@tonic-gate #include <errno.h>
55*7c478bd9Sstevel@tonic-gate #include <synch.h>
56*7c478bd9Sstevel@tonic-gate #include <dlfcn.h>
57*7c478bd9Sstevel@tonic-gate #include <libintl.h>
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN
61*7c478bd9Sstevel@tonic-gate #error TEXT_DOMAIN not defined
62*7c478bd9Sstevel@tonic-gate #endif
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate #define	MECH_CONF "/etc/gss/mech"
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX1	"/usr/lib/"
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate /*
69*7c478bd9Sstevel@tonic-gate  * This #ifdef mess figures out if we are to be compiled into
70*7c478bd9Sstevel@tonic-gate  * a sparcv9/lp64 binary for the purposes of figuring the absolute location
71*7c478bd9Sstevel@tonic-gate  * of gss-api mechanism modules.
72*7c478bd9Sstevel@tonic-gate  */
73*7c478bd9Sstevel@tonic-gate #ifdef	_LP64
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate #ifdef	__sparc
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX2	"sparcv9/"
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate #elif defined(__amd64)
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX2	"amd64/"
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate #else	/* __sparc */
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate you need to define where under /usr the LP64 libraries live for this platform
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate #endif	/* __sparc */
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate #else	/* _LP64 */
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX2	""
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate #endif	/* _LP64 */
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate #define	MECH_LIB_DIR		"gss/"
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX	MECH_LIB_PREFIX1 MECH_LIB_PREFIX2 MECH_LIB_DIR
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate #ifndef	MECH_SYM
101*7c478bd9Sstevel@tonic-gate #define	MECH_SYM "gss_mech_initialize"
102*7c478bd9Sstevel@tonic-gate #endif
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate #define	M_DEFAULT	"default"
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate /* Local functions */
107*7c478bd9Sstevel@tonic-gate static gss_mech_info searchMechList(const gss_OID);
108*7c478bd9Sstevel@tonic-gate static void loadConfigFile(const char *);
109*7c478bd9Sstevel@tonic-gate static void updateMechList(void);
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate /*
113*7c478bd9Sstevel@tonic-gate  * list of mechanism libraries and their entry points.
114*7c478bd9Sstevel@tonic-gate  * the list also maintains state of the mech libraries (loaded or not).
115*7c478bd9Sstevel@tonic-gate  */
116*7c478bd9Sstevel@tonic-gate static gss_mech_info g_mechList = NULL;
117*7c478bd9Sstevel@tonic-gate static gss_mech_info g_mechListTail = NULL;
118*7c478bd9Sstevel@tonic-gate static mutex_t g_mechListLock;
119*7c478bd9Sstevel@tonic-gate static time_t g_confFileModTime = (time_t)0;
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate /*
122*7c478bd9Sstevel@tonic-gate  * function used to reclaim the memory used by a gss_OID structure.
123*7c478bd9Sstevel@tonic-gate  * This routine requires direct access to the mechList.
124*7c478bd9Sstevel@tonic-gate  */
125*7c478bd9Sstevel@tonic-gate OM_uint32
126*7c478bd9Sstevel@tonic-gate gss_release_oid(minor_status, oid)
127*7c478bd9Sstevel@tonic-gate OM_uint32 *minor_status;
128*7c478bd9Sstevel@tonic-gate gss_OID *oid;
129*7c478bd9Sstevel@tonic-gate {
130*7c478bd9Sstevel@tonic-gate 	OM_uint32 major;
131*7c478bd9Sstevel@tonic-gate 	gss_mech_info aMech = g_mechList;
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	if (minor_status == NULL)
134*7c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	*minor_status = 0;
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 	while (aMech != NULL) {
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 		/*
141*7c478bd9Sstevel@tonic-gate 		 * look through the loaded mechanism libraries for
142*7c478bd9Sstevel@tonic-gate 		 * gss_internal_release_oid until one returns success.
143*7c478bd9Sstevel@tonic-gate 		 * gss_internal_release_oid will only return success when
144*7c478bd9Sstevel@tonic-gate 		 * the OID was recognized as an internal mechanism OID. if no
145*7c478bd9Sstevel@tonic-gate 		 * mechanisms recognize the OID, then call the generic version.
146*7c478bd9Sstevel@tonic-gate 		 */
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 		/*
149*7c478bd9Sstevel@tonic-gate 		 * we can walk the mechanism list without a mutex, because we
150*7c478bd9Sstevel@tonic-gate 		 * are only looking at fields which once read will never change.
151*7c478bd9Sstevel@tonic-gate 		 * Mechanism entries are always added to the end, and as
152*7c478bd9Sstevel@tonic-gate 		 * complete entries.
153*7c478bd9Sstevel@tonic-gate 		 */
154*7c478bd9Sstevel@tonic-gate 		if (aMech->mech && aMech->mech->gss_internal_release_oid) {
155*7c478bd9Sstevel@tonic-gate 			major = aMech->mech->gss_internal_release_oid(
156*7c478bd9Sstevel@tonic-gate 					aMech->mech->context,
157*7c478bd9Sstevel@tonic-gate 					minor_status, oid);
158*7c478bd9Sstevel@tonic-gate 			if (major == GSS_S_COMPLETE)
159*7c478bd9Sstevel@tonic-gate 				return (GSS_S_COMPLETE);
160*7c478bd9Sstevel@tonic-gate 		}
161*7c478bd9Sstevel@tonic-gate 		aMech = aMech->next;
162*7c478bd9Sstevel@tonic-gate 	} /* while */
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	return (generic_gss_release_oid(minor_status, oid));
165*7c478bd9Sstevel@tonic-gate } /* gss_release_oid */
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate /*
169*7c478bd9Sstevel@tonic-gate  * this function will return an oid set indicating available mechanisms.
170*7c478bd9Sstevel@tonic-gate  * The set returned is based on configuration file entries and
171*7c478bd9Sstevel@tonic-gate  * NOT on the loaded mechanisms.  This function does not check if any
172*7c478bd9Sstevel@tonic-gate  * of these can actually be loaded.
173*7c478bd9Sstevel@tonic-gate  * This routine needs direct access to the mechanism list.
174*7c478bd9Sstevel@tonic-gate  * To avoid reading the configuration file each call, we will save a
175*7c478bd9Sstevel@tonic-gate  * a mech oid set, and only update it once the file has changed.
176*7c478bd9Sstevel@tonic-gate  */
177*7c478bd9Sstevel@tonic-gate static time_t g_mechSetTime = (time_t)0;
178*7c478bd9Sstevel@tonic-gate static gss_OID_set_desc g_mechSet = { 0, NULL };
179*7c478bd9Sstevel@tonic-gate static mutex_t g_mechSetLock;
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate OM_uint32
183*7c478bd9Sstevel@tonic-gate gss_indicate_mechs(minorStatus, mechSet)
184*7c478bd9Sstevel@tonic-gate OM_uint32 *minorStatus;
185*7c478bd9Sstevel@tonic-gate gss_OID_set *mechSet;
186*7c478bd9Sstevel@tonic-gate {
187*7c478bd9Sstevel@tonic-gate 	gss_mech_info mList;
188*7c478bd9Sstevel@tonic-gate 	char *fileName;
189*7c478bd9Sstevel@tonic-gate 	struct stat fileInfo;
190*7c478bd9Sstevel@tonic-gate 	int count, i, j;
191*7c478bd9Sstevel@tonic-gate 	gss_OID curItem;
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	if (!minorStatus)
194*7c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	*minorStatus = 0;
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	/* check output parameter */
200*7c478bd9Sstevel@tonic-gate 	if (mechSet == NULL)
201*7c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 	fileName = MECH_CONF;
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 	/*
206*7c478bd9Sstevel@tonic-gate 	 * If we have already computed the mechanisms supported and if it
207*7c478bd9Sstevel@tonic-gate 	 * is still valid; make a copy and return to caller,
208*7c478bd9Sstevel@tonic-gate 	 * otherwise build it first.
209*7c478bd9Sstevel@tonic-gate 	 */
210*7c478bd9Sstevel@tonic-gate 	if ((stat(fileName, &fileInfo) == 0 &&
211*7c478bd9Sstevel@tonic-gate 		fileInfo.st_mtime > g_mechSetTime)) {
212*7c478bd9Sstevel@tonic-gate 		/*
213*7c478bd9Sstevel@tonic-gate 		 * lock the mutex since we will be updating
214*7c478bd9Sstevel@tonic-gate 		 * the mechList structure
215*7c478bd9Sstevel@tonic-gate 		 * we need to keep the lock while we build the mechanism list
216*7c478bd9Sstevel@tonic-gate 		 * since we are accessing parts of the mechList which could be
217*7c478bd9Sstevel@tonic-gate 		 * modified.
218*7c478bd9Sstevel@tonic-gate 		 */
219*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&g_mechListLock);
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate 		/*
222*7c478bd9Sstevel@tonic-gate 		 * this checks for the case when we need to re-construct the
223*7c478bd9Sstevel@tonic-gate 		 * g_mechSet structure, but the mechanism list is upto date
224*7c478bd9Sstevel@tonic-gate 		 * (because it has been read by someone calling
225*7c478bd9Sstevel@tonic-gate 		 * __gss_get_mechanism)
226*7c478bd9Sstevel@tonic-gate 		 */
227*7c478bd9Sstevel@tonic-gate 		if (fileInfo.st_mtime > g_confFileModTime)
228*7c478bd9Sstevel@tonic-gate 		{
229*7c478bd9Sstevel@tonic-gate 			g_confFileModTime = fileInfo.st_mtime;
230*7c478bd9Sstevel@tonic-gate 			loadConfigFile(fileName);
231*7c478bd9Sstevel@tonic-gate 		}
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 		/*
234*7c478bd9Sstevel@tonic-gate 		 * we need to lock the mech set so that no one else will
235*7c478bd9Sstevel@tonic-gate 		 * try to read it as we are re-creating it
236*7c478bd9Sstevel@tonic-gate 		 */
237*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&g_mechSetLock);
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 		/* if the oid list already exists we must free it first */
240*7c478bd9Sstevel@tonic-gate 		if (g_mechSet.count != 0) {
241*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < g_mechSet.count; i++)
242*7c478bd9Sstevel@tonic-gate 				free(g_mechSet.elements[i].elements);
243*7c478bd9Sstevel@tonic-gate 			free(g_mechSet.elements);
244*7c478bd9Sstevel@tonic-gate 			g_mechSet.elements = NULL;
245*7c478bd9Sstevel@tonic-gate 			g_mechSet.count = 0;
246*7c478bd9Sstevel@tonic-gate 		}
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 		/* determine how many elements to have in the list */
249*7c478bd9Sstevel@tonic-gate 		mList = g_mechList;
250*7c478bd9Sstevel@tonic-gate 		count = 0;
251*7c478bd9Sstevel@tonic-gate 		while (mList != NULL) {
252*7c478bd9Sstevel@tonic-gate 			count++;
253*7c478bd9Sstevel@tonic-gate 			mList = mList->next;
254*7c478bd9Sstevel@tonic-gate 		}
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 		/* this should always be true, but.... */
257*7c478bd9Sstevel@tonic-gate 		if (count > 0) {
258*7c478bd9Sstevel@tonic-gate 			g_mechSet.elements =
259*7c478bd9Sstevel@tonic-gate 				(gss_OID) calloc(count, sizeof (gss_OID_desc));
260*7c478bd9Sstevel@tonic-gate 			if (g_mechSet.elements == NULL) {
261*7c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&g_mechSetLock);
262*7c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&g_mechListLock);
263*7c478bd9Sstevel@tonic-gate 				return (GSS_S_FAILURE);
264*7c478bd9Sstevel@tonic-gate 			}
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 			(void) memset(g_mechSet.elements, 0,
267*7c478bd9Sstevel@tonic-gate 				count * sizeof (gss_OID_desc));
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 			/* now copy each oid element */
270*7c478bd9Sstevel@tonic-gate 			g_mechSet.count = count;
271*7c478bd9Sstevel@tonic-gate 			count = 0;
272*7c478bd9Sstevel@tonic-gate 			mList = g_mechList;
273*7c478bd9Sstevel@tonic-gate 			while (mList != NULL) {
274*7c478bd9Sstevel@tonic-gate 				curItem = &(g_mechSet.elements[count]);
275*7c478bd9Sstevel@tonic-gate 				curItem->elements = (void*)
276*7c478bd9Sstevel@tonic-gate 					malloc(mList->mech_type->length);
277*7c478bd9Sstevel@tonic-gate 				if (curItem->elements == NULL) {
278*7c478bd9Sstevel@tonic-gate 					/*
279*7c478bd9Sstevel@tonic-gate 					 * this is nasty - we must delete the
280*7c478bd9Sstevel@tonic-gate 					 * part of the array already copied
281*7c478bd9Sstevel@tonic-gate 					 */
282*7c478bd9Sstevel@tonic-gate 					for (i = 0; i < count; i++) {
283*7c478bd9Sstevel@tonic-gate 						free(g_mechSet.elements[i].
284*7c478bd9Sstevel@tonic-gate 							elements);
285*7c478bd9Sstevel@tonic-gate 					}
286*7c478bd9Sstevel@tonic-gate 					free(g_mechSet.elements);
287*7c478bd9Sstevel@tonic-gate 					g_mechSet.count = 0;
288*7c478bd9Sstevel@tonic-gate 					g_mechSet.elements = NULL;
289*7c478bd9Sstevel@tonic-gate 					(void) mutex_unlock(&g_mechSetLock);
290*7c478bd9Sstevel@tonic-gate 					(void) mutex_unlock(&g_mechListLock);
291*7c478bd9Sstevel@tonic-gate 					return (GSS_S_FAILURE);
292*7c478bd9Sstevel@tonic-gate 				}
293*7c478bd9Sstevel@tonic-gate 				g_OID_copy(curItem, mList->mech_type);
294*7c478bd9Sstevel@tonic-gate 				count++;
295*7c478bd9Sstevel@tonic-gate 				mList = mList->next;
296*7c478bd9Sstevel@tonic-gate 			}
297*7c478bd9Sstevel@tonic-gate 		}
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 		g_mechSetTime = fileInfo.st_mtime;
300*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechSetLock);
301*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
302*7c478bd9Sstevel@tonic-gate 	} /* if g_mechSet is out of date or not initialized */
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	/*
305*7c478bd9Sstevel@tonic-gate 	 * the mech set is created and it is up to date
306*7c478bd9Sstevel@tonic-gate 	 * so just copy it to caller
307*7c478bd9Sstevel@tonic-gate 	 */
308*7c478bd9Sstevel@tonic-gate 	if ((*mechSet =
309*7c478bd9Sstevel@tonic-gate 		(gss_OID_set) malloc(sizeof (gss_OID_set_desc))) == NULL)
310*7c478bd9Sstevel@tonic-gate 	{
311*7c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
312*7c478bd9Sstevel@tonic-gate 	}
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate 	/*
315*7c478bd9Sstevel@tonic-gate 	 * need to lock the g_mechSet in case someone tries to update it while
316*7c478bd9Sstevel@tonic-gate 	 * I'm copying it.
317*7c478bd9Sstevel@tonic-gate 	 */
318*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechSetLock);
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 	/* allocate space for the oid structures */
321*7c478bd9Sstevel@tonic-gate 	if (((*mechSet)->elements =
322*7c478bd9Sstevel@tonic-gate 		(void*) calloc(g_mechSet.count, sizeof (gss_OID_desc)))
323*7c478bd9Sstevel@tonic-gate 		== NULL)
324*7c478bd9Sstevel@tonic-gate 	{
325*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechSetLock);
326*7c478bd9Sstevel@tonic-gate 		free(*mechSet);
327*7c478bd9Sstevel@tonic-gate 		*mechSet = NULL;
328*7c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
329*7c478bd9Sstevel@tonic-gate 	}
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 	/* now copy the oid structures */
332*7c478bd9Sstevel@tonic-gate 	(void) memcpy((*mechSet)->elements, g_mechSet.elements,
333*7c478bd9Sstevel@tonic-gate 		g_mechSet.count * sizeof (gss_OID_desc));
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	(*mechSet)->count = g_mechSet.count;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	/* still need to copy each of the oid elements arrays */
338*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < (*mechSet)->count; i++) {
339*7c478bd9Sstevel@tonic-gate 		curItem = &((*mechSet)->elements[i]);
340*7c478bd9Sstevel@tonic-gate 		curItem->elements =
341*7c478bd9Sstevel@tonic-gate 			(void *) malloc(g_mechSet.elements[i].length);
342*7c478bd9Sstevel@tonic-gate 		if (curItem->elements == NULL) {
343*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&g_mechSetLock);
344*7c478bd9Sstevel@tonic-gate 			/*
345*7c478bd9Sstevel@tonic-gate 			 * must still free the allocated elements for
346*7c478bd9Sstevel@tonic-gate 			 * each allocated gss_OID_desc
347*7c478bd9Sstevel@tonic-gate 			 */
348*7c478bd9Sstevel@tonic-gate 			for (j = 0; j < i; j++) {
349*7c478bd9Sstevel@tonic-gate 				free((*mechSet)->elements[j].elements);
350*7c478bd9Sstevel@tonic-gate 			}
351*7c478bd9Sstevel@tonic-gate 			free((*mechSet)->elements);
352*7c478bd9Sstevel@tonic-gate 			free(mechSet);
353*7c478bd9Sstevel@tonic-gate 			*mechSet = NULL;
354*7c478bd9Sstevel@tonic-gate 			return (GSS_S_FAILURE);
355*7c478bd9Sstevel@tonic-gate 		}
356*7c478bd9Sstevel@tonic-gate 		g_OID_copy(curItem, &g_mechSet.elements[i]);
357*7c478bd9Sstevel@tonic-gate 	}
358*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechSetLock);
359*7c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
360*7c478bd9Sstevel@tonic-gate } /* gss_indicate_mechs */
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate /*
363*7c478bd9Sstevel@tonic-gate  * this function has been added for use by modules that need to
364*7c478bd9Sstevel@tonic-gate  * know what (if any) optional parameters are supplied in the
365*7c478bd9Sstevel@tonic-gate  * config file (MECH_CONF).
366*7c478bd9Sstevel@tonic-gate  * It will return the option string for a specified mechanism.
367*7c478bd9Sstevel@tonic-gate  * caller is responsible for freeing the memory
368*7c478bd9Sstevel@tonic-gate  */
369*7c478bd9Sstevel@tonic-gate char *
370*7c478bd9Sstevel@tonic-gate __gss_get_modOptions(oid)
371*7c478bd9Sstevel@tonic-gate const gss_OID oid;
372*7c478bd9Sstevel@tonic-gate {
373*7c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
374*7c478bd9Sstevel@tonic-gate 	char *modOptions = NULL;
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	/* make sure we have fresh data */
377*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
378*7c478bd9Sstevel@tonic-gate 	updateMechList();
379*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 	/* searching the list does not require a lock */
382*7c478bd9Sstevel@tonic-gate 	if ((aMech = searchMechList(oid)) == NULL ||
383*7c478bd9Sstevel@tonic-gate 		aMech->optionStr == NULL) {
384*7c478bd9Sstevel@tonic-gate 		return (NULL);
385*7c478bd9Sstevel@tonic-gate 	}
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	/*
388*7c478bd9Sstevel@tonic-gate 	 * need to obtain a lock on this structure in case someone else
389*7c478bd9Sstevel@tonic-gate 	 * will try to update it during the copy
390*7c478bd9Sstevel@tonic-gate 	 */
391*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
392*7c478bd9Sstevel@tonic-gate 	if (aMech->optionStr)
393*7c478bd9Sstevel@tonic-gate 		modOptions = strdup(aMech->optionStr);
394*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 	return (modOptions);
397*7c478bd9Sstevel@tonic-gate } /* __gss_get_modOptions */
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate /*
400*7c478bd9Sstevel@tonic-gate  * this function has been added for use by gssd.
401*7c478bd9Sstevel@tonic-gate  * It will return the kernel module name for a specified mechanism.
402*7c478bd9Sstevel@tonic-gate  * caller is responsible for freeing the memory
403*7c478bd9Sstevel@tonic-gate  */
404*7c478bd9Sstevel@tonic-gate char *
405*7c478bd9Sstevel@tonic-gate __gss_get_kmodName(oid)
406*7c478bd9Sstevel@tonic-gate const gss_OID oid;
407*7c478bd9Sstevel@tonic-gate {
408*7c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
409*7c478bd9Sstevel@tonic-gate 	char *kmodName = NULL;
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 	/* make sure we have fresh data */
412*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
413*7c478bd9Sstevel@tonic-gate 	updateMechList();
414*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 	/* searching the list does not require a lock */
417*7c478bd9Sstevel@tonic-gate 	if ((aMech = searchMechList(oid)) == NULL || aMech->kmodName == NULL) {
418*7c478bd9Sstevel@tonic-gate 		return (NULL);
419*7c478bd9Sstevel@tonic-gate 	}
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 	/*
422*7c478bd9Sstevel@tonic-gate 	 * need to obtain a lock on this structure in case someone else
423*7c478bd9Sstevel@tonic-gate 	 * will try to update it during the copy
424*7c478bd9Sstevel@tonic-gate 	 */
425*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
426*7c478bd9Sstevel@tonic-gate 	if (aMech->kmodName)
427*7c478bd9Sstevel@tonic-gate 		kmodName = strdup(aMech->kmodName);
428*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 	return (kmodName);
431*7c478bd9Sstevel@tonic-gate } /* __gss_get_kmodName */
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate /*
435*7c478bd9Sstevel@tonic-gate  * given a mechanism string return the mechanism oid
436*7c478bd9Sstevel@tonic-gate  */
437*7c478bd9Sstevel@tonic-gate OM_uint32
438*7c478bd9Sstevel@tonic-gate __gss_mech_to_oid(const char *mechStr, gss_OID* oid)
439*7c478bd9Sstevel@tonic-gate {
440*7c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate 	if (oid == NULL)
443*7c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate 	*oid = GSS_C_NULL_OID;
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	if ((mechStr == NULL) || (strlen(mechStr) == 0) ||
448*7c478bd9Sstevel@tonic-gate 		(strcasecmp(mechStr, M_DEFAULT) == 0))
449*7c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 	/* ensure we have fresh data */
452*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
453*7c478bd9Sstevel@tonic-gate 	updateMechList();
454*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 	aMech = g_mechList;
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 	/* no lock required - only looking at fields that are not updated */
459*7c478bd9Sstevel@tonic-gate 	while (aMech != NULL) {
460*7c478bd9Sstevel@tonic-gate 		if ((aMech->mechNameStr) &&
461*7c478bd9Sstevel@tonic-gate 			strcmp(aMech->mechNameStr, mechStr) == 0) {
462*7c478bd9Sstevel@tonic-gate 			*oid = aMech->mech_type;
463*7c478bd9Sstevel@tonic-gate 			return (GSS_S_COMPLETE);
464*7c478bd9Sstevel@tonic-gate 		}
465*7c478bd9Sstevel@tonic-gate 		aMech = aMech->next;
466*7c478bd9Sstevel@tonic-gate 	}
467*7c478bd9Sstevel@tonic-gate 	return (GSS_S_FAILURE);
468*7c478bd9Sstevel@tonic-gate } /* __gss_mech_to_oid */
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate /*
472*7c478bd9Sstevel@tonic-gate  * Given the mechanism oid, return the readable mechanism name
473*7c478bd9Sstevel@tonic-gate  * associated with that oid from the mech config file
474*7c478bd9Sstevel@tonic-gate  * (/etc/gss/mech).
475*7c478bd9Sstevel@tonic-gate  */
476*7c478bd9Sstevel@tonic-gate const char *
477*7c478bd9Sstevel@tonic-gate __gss_oid_to_mech(const gss_OID oid)
478*7c478bd9Sstevel@tonic-gate {
479*7c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 	if (oid == GSS_C_NULL_OID)
482*7c478bd9Sstevel@tonic-gate 		return (M_DEFAULT);
483*7c478bd9Sstevel@tonic-gate 
484*7c478bd9Sstevel@tonic-gate 	/* ensure we have fresh data */
485*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
486*7c478bd9Sstevel@tonic-gate 	updateMechList();
487*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	if ((aMech = searchMechList(oid)) == NULL)
490*7c478bd9Sstevel@tonic-gate 		return (NULL);
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate 	return (aMech->mechNameStr);
493*7c478bd9Sstevel@tonic-gate } /* __gss_oid_to_mech */
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate /*
497*7c478bd9Sstevel@tonic-gate  * return a list of mechanism strings supported
498*7c478bd9Sstevel@tonic-gate  * upon return the array is terminated with a NULL entry
499*7c478bd9Sstevel@tonic-gate  */
500*7c478bd9Sstevel@tonic-gate OM_uint32
501*7c478bd9Sstevel@tonic-gate __gss_get_mechanisms(char *mechArray[], int arrayLen)
502*7c478bd9Sstevel@tonic-gate {
503*7c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
504*7c478bd9Sstevel@tonic-gate 	int i;
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate 	if (mechArray == NULL || arrayLen < 1)
507*7c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate 	/* ensure we have fresh data */
510*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
511*7c478bd9Sstevel@tonic-gate 	updateMechList();
512*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	aMech = g_mechList;
515*7c478bd9Sstevel@tonic-gate 
516*7c478bd9Sstevel@tonic-gate 	/* no lock required - only looking at fields that are not updated */
517*7c478bd9Sstevel@tonic-gate 	for (i = 1; i < arrayLen; i++) {
518*7c478bd9Sstevel@tonic-gate 		if (aMech != NULL) {
519*7c478bd9Sstevel@tonic-gate 			*mechArray = aMech->mechNameStr;
520*7c478bd9Sstevel@tonic-gate 			mechArray++;
521*7c478bd9Sstevel@tonic-gate 			aMech = aMech->next;
522*7c478bd9Sstevel@tonic-gate 		} else
523*7c478bd9Sstevel@tonic-gate 			break;
524*7c478bd9Sstevel@tonic-gate 	}
525*7c478bd9Sstevel@tonic-gate 	*mechArray = NULL;
526*7c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
527*7c478bd9Sstevel@tonic-gate } /* gss_get_mechanisms */
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 
530*7c478bd9Sstevel@tonic-gate /*
531*7c478bd9Sstevel@tonic-gate  * determines if the mechList needs to be updated from file
532*7c478bd9Sstevel@tonic-gate  * and performs the update.
533*7c478bd9Sstevel@tonic-gate  * this functions must be called with a lock of g_mechListLock
534*7c478bd9Sstevel@tonic-gate  */
535*7c478bd9Sstevel@tonic-gate static void
536*7c478bd9Sstevel@tonic-gate updateMechList(void)
537*7c478bd9Sstevel@tonic-gate {
538*7c478bd9Sstevel@tonic-gate 	char *fileName;
539*7c478bd9Sstevel@tonic-gate 	struct stat fileInfo;
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 	fileName = MECH_CONF;
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 	/* check if mechList needs updating */
544*7c478bd9Sstevel@tonic-gate 	if (stat(fileName, &fileInfo) == 0 &&
545*7c478bd9Sstevel@tonic-gate 		(fileInfo.st_mtime > g_confFileModTime)) {
546*7c478bd9Sstevel@tonic-gate 		loadConfigFile(fileName);
547*7c478bd9Sstevel@tonic-gate 		g_confFileModTime = fileInfo.st_mtime;
548*7c478bd9Sstevel@tonic-gate 	}
549*7c478bd9Sstevel@tonic-gate } /* updateMechList */
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate /*
553*7c478bd9Sstevel@tonic-gate  * given the mechanism type, return the mechanism structure
554*7c478bd9Sstevel@tonic-gate  * containing the mechanism library entry points.
555*7c478bd9Sstevel@tonic-gate  * will return NULL if mech type is not found
556*7c478bd9Sstevel@tonic-gate  * This function will also trigger the loading of the mechanism
557*7c478bd9Sstevel@tonic-gate  * module if it has not been already loaded.
558*7c478bd9Sstevel@tonic-gate  */
559*7c478bd9Sstevel@tonic-gate gss_mechanism
560*7c478bd9Sstevel@tonic-gate __gss_get_mechanism(oid)
561*7c478bd9Sstevel@tonic-gate const gss_OID oid;
562*7c478bd9Sstevel@tonic-gate {
563*7c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
564*7c478bd9Sstevel@tonic-gate 	gss_mechanism (*sym)(const gss_OID);
565*7c478bd9Sstevel@tonic-gate 	void *dl;
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	/* check if the mechanism is already loaded */
568*7c478bd9Sstevel@tonic-gate 	if ((aMech = searchMechList(oid)) != NULL && aMech->mech) {
569*7c478bd9Sstevel@tonic-gate 		return (aMech->mech);
570*7c478bd9Sstevel@tonic-gate 	}
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate 	/*
573*7c478bd9Sstevel@tonic-gate 	 * might need to re-read the configuration file before loading
574*7c478bd9Sstevel@tonic-gate 	 * the mechanism to ensure we have the latest info.
575*7c478bd9Sstevel@tonic-gate 	 */
576*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
577*7c478bd9Sstevel@tonic-gate 	updateMechList();
578*7c478bd9Sstevel@tonic-gate 
579*7c478bd9Sstevel@tonic-gate 	aMech = searchMechList(oid);
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate 	/* is the mechanism present in the list ? */
582*7c478bd9Sstevel@tonic-gate 	if (aMech == NULL) {
583*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
584*7c478bd9Sstevel@tonic-gate 		return ((gss_mechanism)NULL);
585*7c478bd9Sstevel@tonic-gate 	}
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 	/* has another thread loaded the mech */
588*7c478bd9Sstevel@tonic-gate 	if (aMech->mech) {
589*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
590*7c478bd9Sstevel@tonic-gate 		return (aMech->mech);
591*7c478bd9Sstevel@tonic-gate 	}
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 	/* we found the mechanism, but it is not loaded */
594*7c478bd9Sstevel@tonic-gate 	if ((dl = dlopen(aMech->uLibName, RTLD_NOW)) == NULL) {
595*7c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n",
596*7c478bd9Sstevel@tonic-gate 				aMech->uLibName, dlerror());
597*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
598*7c478bd9Sstevel@tonic-gate 		return ((gss_mechanism)NULL);
599*7c478bd9Sstevel@tonic-gate 	}
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 	if ((sym = (gss_mechanism (*)(const gss_OID))dlsym(dl, MECH_SYM))
602*7c478bd9Sstevel@tonic-gate 			== NULL) {
603*7c478bd9Sstevel@tonic-gate 		(void) dlclose(dl);
604*7c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_INFO, "unable to initialize mechanism"
605*7c478bd9Sstevel@tonic-gate 				" library [%s]\n", aMech->uLibName);
606*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
607*7c478bd9Sstevel@tonic-gate 		return ((gss_mechanism)NULL);
608*7c478bd9Sstevel@tonic-gate 	}
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 	/* Call the symbol to get the mechanism table */
611*7c478bd9Sstevel@tonic-gate 	aMech->mech = (*sym)(aMech->mech_type);
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate 	if (aMech->mech == NULL) {
614*7c478bd9Sstevel@tonic-gate 		(void) dlclose(dl);
615*7c478bd9Sstevel@tonic-gate 		(void) syslog(LOG_INFO, "unable to initialize mechanism"
616*7c478bd9Sstevel@tonic-gate 				" library [%s]\n", aMech->uLibName);
617*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&g_mechListLock);
618*7c478bd9Sstevel@tonic-gate 		return ((gss_mechanism)NULL);
619*7c478bd9Sstevel@tonic-gate 	}
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate 	aMech->dl_handle = dl;
622*7c478bd9Sstevel@tonic-gate 
623*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
624*7c478bd9Sstevel@tonic-gate 	return (aMech->mech);
625*7c478bd9Sstevel@tonic-gate } /* __gss_get_mechanism */
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate gss_mechanism_ext
628*7c478bd9Sstevel@tonic-gate __gss_get_mechanism_ext(oid)
629*7c478bd9Sstevel@tonic-gate const gss_OID oid;
630*7c478bd9Sstevel@tonic-gate {
631*7c478bd9Sstevel@tonic-gate 	gss_mech_info aMech;
632*7c478bd9Sstevel@tonic-gate 	gss_mechanism_ext mech_ext;
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 	/* check if the mechanism is already loaded */
635*7c478bd9Sstevel@tonic-gate 	if ((aMech = searchMechList(oid)) != NULL && aMech->mech_ext != NULL)
636*7c478bd9Sstevel@tonic-gate 		return (aMech->mech_ext);
637*7c478bd9Sstevel@tonic-gate 
638*7c478bd9Sstevel@tonic-gate 	if (__gss_get_mechanism(oid) == NULL)
639*7c478bd9Sstevel@tonic-gate 		return (NULL);
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate 	if (aMech->dl_handle == NULL)
642*7c478bd9Sstevel@tonic-gate 		return (NULL);
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 	/* Load the gss_config_ext struct for this mech */
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 	mech_ext = (gss_mechanism_ext)malloc(sizeof (struct gss_config_ext));
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 	if (mech_ext == NULL)
649*7c478bd9Sstevel@tonic-gate 		return (NULL);
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 	/*
652*7c478bd9Sstevel@tonic-gate 	 * dlsym() the mech's 'method' functions for the extended APIs
653*7c478bd9Sstevel@tonic-gate 	 *
654*7c478bd9Sstevel@tonic-gate 	 * NOTE:  Until the void *context argument is removed from the
655*7c478bd9Sstevel@tonic-gate 	 * SPI method functions' signatures it will be necessary to have
656*7c478bd9Sstevel@tonic-gate 	 * different function pointer typedefs and function names for
657*7c478bd9Sstevel@tonic-gate 	 * the SPI methods than for the API.  When this argument is
658*7c478bd9Sstevel@tonic-gate 	 * removed it will be possible to rename gss_*_sfct to gss_*_fct
659*7c478bd9Sstevel@tonic-gate 	 * and and gssspi_* to gss_*.
660*7c478bd9Sstevel@tonic-gate 	 */
661*7c478bd9Sstevel@tonic-gate 	mech_ext->gss_acquire_cred_with_password =
662*7c478bd9Sstevel@tonic-gate 		(gss_acquire_cred_with_password_sfct)dlsym(aMech->dl_handle,
663*7c478bd9Sstevel@tonic-gate 			"gssspi_acquire_cred_with_password");
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 	/* Set aMech->mech_ext */
666*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&g_mechListLock);
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate 	if (aMech->mech_ext == NULL)
669*7c478bd9Sstevel@tonic-gate 		aMech->mech_ext = mech_ext;
670*7c478bd9Sstevel@tonic-gate 	else
671*7c478bd9Sstevel@tonic-gate 		free(mech_ext);	/* we raced and lost; don't leak */
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&g_mechListLock);
674*7c478bd9Sstevel@tonic-gate 
675*7c478bd9Sstevel@tonic-gate 	return (aMech->mech_ext);
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate } /* __gss_get_mechanism_ext */
678*7c478bd9Sstevel@tonic-gate 
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate /*
681*7c478bd9Sstevel@tonic-gate  * this routine is used for searching the list of mechanism data.
682*7c478bd9Sstevel@tonic-gate  * it needs not be mutex protected because we only add new structures
683*7c478bd9Sstevel@tonic-gate  * from the end and they are fully initialized before being added.
684*7c478bd9Sstevel@tonic-gate  */
685*7c478bd9Sstevel@tonic-gate static gss_mech_info searchMechList(oid)
686*7c478bd9Sstevel@tonic-gate const gss_OID oid;
687*7c478bd9Sstevel@tonic-gate {
688*7c478bd9Sstevel@tonic-gate 	gss_mech_info aMech = g_mechList;
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate 	/* if oid is null -> then get default which is the first in the list */
691*7c478bd9Sstevel@tonic-gate 	if (oid == GSS_C_NULL_OID)
692*7c478bd9Sstevel@tonic-gate 		return (aMech);
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	while (aMech != NULL) {
695*7c478bd9Sstevel@tonic-gate 		if (g_OID_equal(aMech->mech_type, oid))
696*7c478bd9Sstevel@tonic-gate 			return (aMech);
697*7c478bd9Sstevel@tonic-gate 		aMech = aMech->next;
698*7c478bd9Sstevel@tonic-gate 	}
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate 	/* none found */
701*7c478bd9Sstevel@tonic-gate 	return ((gss_mech_info) NULL);
702*7c478bd9Sstevel@tonic-gate } /* searchMechList */
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate /*
706*7c478bd9Sstevel@tonic-gate  * loads the configuration file
707*7c478bd9Sstevel@tonic-gate  * this is called while having a mutex lock on the mechanism list
708*7c478bd9Sstevel@tonic-gate  * entries for libraries that have been loaded can't be modified
709*7c478bd9Sstevel@tonic-gate  * mechNameStr and mech_type fields are not updated during updates
710*7c478bd9Sstevel@tonic-gate  */
711*7c478bd9Sstevel@tonic-gate static void loadConfigFile(fileName)
712*7c478bd9Sstevel@tonic-gate const char *fileName;
713*7c478bd9Sstevel@tonic-gate {
714*7c478bd9Sstevel@tonic-gate 	char buffer[BUFSIZ], *oidStr, *oid, *sharedLib, *kernMod, *endp;
715*7c478bd9Sstevel@tonic-gate 	char *modOptions;
716*7c478bd9Sstevel@tonic-gate 	char sharedPath[sizeof (MECH_LIB_PREFIX) + BUFSIZ];
717*7c478bd9Sstevel@tonic-gate 	char *tmpStr;
718*7c478bd9Sstevel@tonic-gate 	FILE *confFile;
719*7c478bd9Sstevel@tonic-gate 	gss_OID mechOid;
720*7c478bd9Sstevel@tonic-gate 	gss_mech_info aMech, tmp;
721*7c478bd9Sstevel@tonic-gate 	OM_uint32 minor;
722*7c478bd9Sstevel@tonic-gate 	gss_buffer_desc oidBuf;
723*7c478bd9Sstevel@tonic-gate 
724*7c478bd9Sstevel@tonic-gate 	if ((confFile = fopen(fileName, "r")) == NULL) {
725*7c478bd9Sstevel@tonic-gate 		return;
726*7c478bd9Sstevel@tonic-gate 	}
727*7c478bd9Sstevel@tonic-gate 
728*7c478bd9Sstevel@tonic-gate 	(void) memset(buffer, 0, sizeof (buffer));
729*7c478bd9Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, confFile) != NULL) {
730*7c478bd9Sstevel@tonic-gate 
731*7c478bd9Sstevel@tonic-gate 		/* ignore lines beginning with # */
732*7c478bd9Sstevel@tonic-gate 		if (*buffer == '#')
733*7c478bd9Sstevel@tonic-gate 			continue;
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate 		/*
736*7c478bd9Sstevel@tonic-gate 		 * find the first white-space character after
737*7c478bd9Sstevel@tonic-gate 		 * the mechanism name
738*7c478bd9Sstevel@tonic-gate 		 */
739*7c478bd9Sstevel@tonic-gate 		oidStr = buffer;
740*7c478bd9Sstevel@tonic-gate 		for (oid = buffer; *oid && !isspace(*oid); oid++);
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 		/* Now find the first non-white-space character */
743*7c478bd9Sstevel@tonic-gate 		if (*oid) {
744*7c478bd9Sstevel@tonic-gate 			*oid = '\0';
745*7c478bd9Sstevel@tonic-gate 			oid++;
746*7c478bd9Sstevel@tonic-gate 			while (*oid && isspace(*oid))
747*7c478bd9Sstevel@tonic-gate 				oid++;
748*7c478bd9Sstevel@tonic-gate 		}
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 		/*
751*7c478bd9Sstevel@tonic-gate 		 * If that's all, then this is a corrupt entry. Skip it.
752*7c478bd9Sstevel@tonic-gate 		 */
753*7c478bd9Sstevel@tonic-gate 		if (! *oid)
754*7c478bd9Sstevel@tonic-gate 			continue;
755*7c478bd9Sstevel@tonic-gate 
756*7c478bd9Sstevel@tonic-gate 		/* Find the end of the oid and make sure it is NULL-ended */
757*7c478bd9Sstevel@tonic-gate 		for (endp = oid; *endp && !isspace(*endp); endp++)
758*7c478bd9Sstevel@tonic-gate 			;
759*7c478bd9Sstevel@tonic-gate 
760*7c478bd9Sstevel@tonic-gate 		if (*endp) {
761*7c478bd9Sstevel@tonic-gate 			*endp = '\0';
762*7c478bd9Sstevel@tonic-gate 		}
763*7c478bd9Sstevel@tonic-gate 
764*7c478bd9Sstevel@tonic-gate 		/*
765*7c478bd9Sstevel@tonic-gate 		 * check if an entry for this oid already exists
766*7c478bd9Sstevel@tonic-gate 		 * if it does, and the library is already loaded then
767*7c478bd9Sstevel@tonic-gate 		 * we can't modify it, so skip it
768*7c478bd9Sstevel@tonic-gate 		 */
769*7c478bd9Sstevel@tonic-gate 		oidBuf.value = (void *)oid;
770*7c478bd9Sstevel@tonic-gate 		oidBuf.length = strlen(oid);
771*7c478bd9Sstevel@tonic-gate 		if (generic_gss_str_to_oid(&minor, &oidBuf, &mechOid)
772*7c478bd9Sstevel@tonic-gate 			!= GSS_S_COMPLETE) {
773*7c478bd9Sstevel@tonic-gate 			(void) syslog(LOG_INFO, "invalid mechanism oid"
774*7c478bd9Sstevel@tonic-gate 					" [%s] in configuration file", oid);
775*7c478bd9Sstevel@tonic-gate 			continue;
776*7c478bd9Sstevel@tonic-gate 		}
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 		aMech = searchMechList(mechOid);
779*7c478bd9Sstevel@tonic-gate 		if (aMech && aMech->mech) {
780*7c478bd9Sstevel@tonic-gate 			free(mechOid->elements);
781*7c478bd9Sstevel@tonic-gate 			free(mechOid);
782*7c478bd9Sstevel@tonic-gate 			continue;
783*7c478bd9Sstevel@tonic-gate 		}
784*7c478bd9Sstevel@tonic-gate 
785*7c478bd9Sstevel@tonic-gate 		/* Find the start of the shared lib name */
786*7c478bd9Sstevel@tonic-gate 		for (sharedLib = endp+1; *sharedLib && isspace(*sharedLib);
787*7c478bd9Sstevel@tonic-gate 			sharedLib++)
788*7c478bd9Sstevel@tonic-gate 			;
789*7c478bd9Sstevel@tonic-gate 
790*7c478bd9Sstevel@tonic-gate 		/*
791*7c478bd9Sstevel@tonic-gate 		 * If that's all, then this is a corrupt entry. Skip it.
792*7c478bd9Sstevel@tonic-gate 		 */
793*7c478bd9Sstevel@tonic-gate 		if (! *sharedLib) {
794*7c478bd9Sstevel@tonic-gate 			free(mechOid->elements);
795*7c478bd9Sstevel@tonic-gate 			free(mechOid);
796*7c478bd9Sstevel@tonic-gate 			continue;
797*7c478bd9Sstevel@tonic-gate 		}
798*7c478bd9Sstevel@tonic-gate 
799*7c478bd9Sstevel@tonic-gate 		/*
800*7c478bd9Sstevel@tonic-gate 		 * Find the end of the shared lib name and make sure it is
801*7c478bd9Sstevel@tonic-gate 		 *  NULL-terminated.
802*7c478bd9Sstevel@tonic-gate 		 */
803*7c478bd9Sstevel@tonic-gate 		for (endp = sharedLib; *endp && !isspace(*endp); endp++)
804*7c478bd9Sstevel@tonic-gate 			;
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate 		if (*endp) {
807*7c478bd9Sstevel@tonic-gate 			*endp = '\0';
808*7c478bd9Sstevel@tonic-gate 		}
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate 		/* Find the start of the optional kernel module lib name */
811*7c478bd9Sstevel@tonic-gate 		for (kernMod = endp+1; *kernMod && isspace(*kernMod);
812*7c478bd9Sstevel@tonic-gate 			kernMod++)
813*7c478bd9Sstevel@tonic-gate 			;
814*7c478bd9Sstevel@tonic-gate 
815*7c478bd9Sstevel@tonic-gate 		/*
816*7c478bd9Sstevel@tonic-gate 		 * If this item starts with a bracket "[", then
817*7c478bd9Sstevel@tonic-gate 		 * it is not a kernel module, but is a list of
818*7c478bd9Sstevel@tonic-gate 		 * options for the user module to parse later.
819*7c478bd9Sstevel@tonic-gate 		 */
820*7c478bd9Sstevel@tonic-gate 		if (*kernMod && *kernMod != '[') {
821*7c478bd9Sstevel@tonic-gate 			/*
822*7c478bd9Sstevel@tonic-gate 			 * Find the end of the shared lib name and make sure
823*7c478bd9Sstevel@tonic-gate 			 * it is NULL-terminated.
824*7c478bd9Sstevel@tonic-gate 			 */
825*7c478bd9Sstevel@tonic-gate 			for (endp = kernMod; *endp && !isspace(*endp); endp++)
826*7c478bd9Sstevel@tonic-gate 				;
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate 			if (*endp) {
829*7c478bd9Sstevel@tonic-gate 				*endp = '\0';
830*7c478bd9Sstevel@tonic-gate 			}
831*7c478bd9Sstevel@tonic-gate 		} else
832*7c478bd9Sstevel@tonic-gate 			kernMod = NULL;
833*7c478bd9Sstevel@tonic-gate 
834*7c478bd9Sstevel@tonic-gate 		/* Find the start of the optional module options list */
835*7c478bd9Sstevel@tonic-gate 		for (modOptions = endp+1; *modOptions && isspace(*modOptions);
836*7c478bd9Sstevel@tonic-gate 			modOptions++);
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate 		if (*modOptions == '[')  {
839*7c478bd9Sstevel@tonic-gate 			/* move past the opening bracket */
840*7c478bd9Sstevel@tonic-gate 			for (modOptions = modOptions+1;
841*7c478bd9Sstevel@tonic-gate 			    *modOptions && isspace(*modOptions);
842*7c478bd9Sstevel@tonic-gate 			    modOptions++);
843*7c478bd9Sstevel@tonic-gate 
844*7c478bd9Sstevel@tonic-gate 			/* Find the closing bracket */
845*7c478bd9Sstevel@tonic-gate 			for (endp = modOptions;
846*7c478bd9Sstevel@tonic-gate 				*endp && *endp != ']'; endp++);
847*7c478bd9Sstevel@tonic-gate 
848*7c478bd9Sstevel@tonic-gate 			if (endp)
849*7c478bd9Sstevel@tonic-gate 				*endp = '\0';
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate 		} else {
852*7c478bd9Sstevel@tonic-gate 			modOptions = NULL;
853*7c478bd9Sstevel@tonic-gate 		}
854*7c478bd9Sstevel@tonic-gate 
855*7c478bd9Sstevel@tonic-gate 		(void) strcpy(sharedPath, MECH_LIB_PREFIX);
856*7c478bd9Sstevel@tonic-gate 		(void) strcat(sharedPath, sharedLib);
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate 		/*
859*7c478bd9Sstevel@tonic-gate 		 * are we creating a new mechanism entry or
860*7c478bd9Sstevel@tonic-gate 		 * just modifying existing (non loaded) mechanism entry
861*7c478bd9Sstevel@tonic-gate 		 */
862*7c478bd9Sstevel@tonic-gate 		if (aMech) {
863*7c478bd9Sstevel@tonic-gate 			/*
864*7c478bd9Sstevel@tonic-gate 			 * delete any old values and set new
865*7c478bd9Sstevel@tonic-gate 			 * mechNameStr and mech_type are not modified
866*7c478bd9Sstevel@tonic-gate 			 */
867*7c478bd9Sstevel@tonic-gate 			if (aMech->kmodName) {
868*7c478bd9Sstevel@tonic-gate 				free(aMech->kmodName);
869*7c478bd9Sstevel@tonic-gate 				aMech->kmodName = NULL;
870*7c478bd9Sstevel@tonic-gate 			}
871*7c478bd9Sstevel@tonic-gate 
872*7c478bd9Sstevel@tonic-gate 			if (aMech->optionStr) {
873*7c478bd9Sstevel@tonic-gate 				free(aMech->optionStr);
874*7c478bd9Sstevel@tonic-gate 				aMech->optionStr = NULL;
875*7c478bd9Sstevel@tonic-gate 			}
876*7c478bd9Sstevel@tonic-gate 
877*7c478bd9Sstevel@tonic-gate 			if ((tmpStr = strdup(sharedPath)) != NULL) {
878*7c478bd9Sstevel@tonic-gate 				if (aMech->uLibName)
879*7c478bd9Sstevel@tonic-gate 					free(aMech->uLibName);
880*7c478bd9Sstevel@tonic-gate 				aMech->uLibName = tmpStr;
881*7c478bd9Sstevel@tonic-gate 			}
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate 			if (kernMod) /* this is an optional parameter */
884*7c478bd9Sstevel@tonic-gate 				aMech->kmodName = strdup(kernMod);
885*7c478bd9Sstevel@tonic-gate 
886*7c478bd9Sstevel@tonic-gate 			if (modOptions) /* optional module options */
887*7c478bd9Sstevel@tonic-gate 				aMech->optionStr = strdup(modOptions);
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate 			/* the oid is already set */
890*7c478bd9Sstevel@tonic-gate 			free(mechOid->elements);
891*7c478bd9Sstevel@tonic-gate 			free(mechOid);
892*7c478bd9Sstevel@tonic-gate 			continue;
893*7c478bd9Sstevel@tonic-gate 		}
894*7c478bd9Sstevel@tonic-gate 
895*7c478bd9Sstevel@tonic-gate 		/* adding a new entry */
896*7c478bd9Sstevel@tonic-gate 		aMech = malloc(sizeof (struct gss_mech_config));
897*7c478bd9Sstevel@tonic-gate 		if (aMech == NULL) {
898*7c478bd9Sstevel@tonic-gate 			free(mechOid->elements);
899*7c478bd9Sstevel@tonic-gate 			free(mechOid);
900*7c478bd9Sstevel@tonic-gate 			continue;
901*7c478bd9Sstevel@tonic-gate 		}
902*7c478bd9Sstevel@tonic-gate 		(void) memset(aMech, 0, sizeof (struct gss_mech_config));
903*7c478bd9Sstevel@tonic-gate 		aMech->mech_type = mechOid;
904*7c478bd9Sstevel@tonic-gate 		aMech->uLibName = strdup(sharedPath);
905*7c478bd9Sstevel@tonic-gate 		aMech->mechNameStr = strdup(oidStr);
906*7c478bd9Sstevel@tonic-gate 
907*7c478bd9Sstevel@tonic-gate 		/* check if any memory allocations failed - bad news */
908*7c478bd9Sstevel@tonic-gate 		if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) {
909*7c478bd9Sstevel@tonic-gate 			if (aMech->uLibName)
910*7c478bd9Sstevel@tonic-gate 				free(aMech->uLibName);
911*7c478bd9Sstevel@tonic-gate 			if (aMech->mechNameStr)
912*7c478bd9Sstevel@tonic-gate 				free(aMech->mechNameStr);
913*7c478bd9Sstevel@tonic-gate 			free(mechOid->elements);
914*7c478bd9Sstevel@tonic-gate 			free(mechOid);
915*7c478bd9Sstevel@tonic-gate 			free(aMech);
916*7c478bd9Sstevel@tonic-gate 			continue;
917*7c478bd9Sstevel@tonic-gate 		}
918*7c478bd9Sstevel@tonic-gate 		if (kernMod)	/* this is an optional parameter */
919*7c478bd9Sstevel@tonic-gate 			aMech->kmodName = strdup(kernMod);
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 		if (modOptions)
922*7c478bd9Sstevel@tonic-gate 			aMech->optionStr = strdup(modOptions);
923*7c478bd9Sstevel@tonic-gate 		/*
924*7c478bd9Sstevel@tonic-gate 		 * add the new entry to the end of the list - make sure
925*7c478bd9Sstevel@tonic-gate 		 * that only complete entries are added because other
926*7c478bd9Sstevel@tonic-gate 		 * threads might currently be searching the list.
927*7c478bd9Sstevel@tonic-gate 		 */
928*7c478bd9Sstevel@tonic-gate 		tmp = g_mechListTail;
929*7c478bd9Sstevel@tonic-gate 		g_mechListTail = aMech;
930*7c478bd9Sstevel@tonic-gate 
931*7c478bd9Sstevel@tonic-gate 		if (tmp != NULL)
932*7c478bd9Sstevel@tonic-gate 			tmp->next = aMech;
933*7c478bd9Sstevel@tonic-gate 
934*7c478bd9Sstevel@tonic-gate 		if (g_mechList == NULL)
935*7c478bd9Sstevel@tonic-gate 			g_mechList = aMech;
936*7c478bd9Sstevel@tonic-gate 	} /* while */
937*7c478bd9Sstevel@tonic-gate 	(void) fclose(confFile);
938*7c478bd9Sstevel@tonic-gate } /* loadConfigFile */
939