1*7f2fe78bSCy Schubert /* #pragma ident "@(#)g_initialize.c 1.36 05/02/02 SMI" */
2*7f2fe78bSCy Schubert
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright 1996 by Sun Microsystems, Inc.
5*7f2fe78bSCy Schubert *
6*7f2fe78bSCy Schubert * Permission to use, copy, modify, distribute, and sell this software
7*7f2fe78bSCy Schubert * and its documentation for any purpose is hereby granted without fee,
8*7f2fe78bSCy Schubert * provided that the above copyright notice appears in all copies and
9*7f2fe78bSCy Schubert * that both that copyright notice and this permission notice appear in
10*7f2fe78bSCy Schubert * supporting documentation, and that the name of Sun Microsystems not be used
11*7f2fe78bSCy Schubert * in advertising or publicity pertaining to distribution of the software
12*7f2fe78bSCy Schubert * without specific, written prior permission. Sun Microsystems makes no
13*7f2fe78bSCy Schubert * representations about the suitability of this software for any
14*7f2fe78bSCy Schubert * purpose. It is provided "as is" without express or implied warranty.
15*7f2fe78bSCy Schubert *
16*7f2fe78bSCy Schubert * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17*7f2fe78bSCy Schubert * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18*7f2fe78bSCy Schubert * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19*7f2fe78bSCy Schubert * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20*7f2fe78bSCy Schubert * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21*7f2fe78bSCy Schubert * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22*7f2fe78bSCy Schubert * PERFORMANCE OF THIS SOFTWARE.
23*7f2fe78bSCy Schubert */
24*7f2fe78bSCy Schubert
25*7f2fe78bSCy Schubert /*
26*7f2fe78bSCy Schubert * This function will initialize the gssapi mechglue library
27*7f2fe78bSCy Schubert */
28*7f2fe78bSCy Schubert
29*7f2fe78bSCy Schubert #include "mglueP.h"
30*7f2fe78bSCy Schubert #ifdef HAVE_STDLIB_H
31*7f2fe78bSCy Schubert #include <stdlib.h>
32*7f2fe78bSCy Schubert #endif
33*7f2fe78bSCy Schubert #ifdef HAVE_SYS_STAT_H
34*7f2fe78bSCy Schubert #include <sys/stat.h>
35*7f2fe78bSCy Schubert #endif
36*7f2fe78bSCy Schubert #ifdef HAVE_SYS_PARAM_H
37*7f2fe78bSCy Schubert #include <sys/param.h>
38*7f2fe78bSCy Schubert #endif
39*7f2fe78bSCy Schubert
40*7f2fe78bSCy Schubert #include <stdio.h>
41*7f2fe78bSCy Schubert #include <string.h>
42*7f2fe78bSCy Schubert #include <ctype.h>
43*7f2fe78bSCy Schubert #include <errno.h>
44*7f2fe78bSCy Schubert #ifndef _WIN32
45*7f2fe78bSCy Schubert #include <glob.h>
46*7f2fe78bSCy Schubert #endif
47*7f2fe78bSCy Schubert
48*7f2fe78bSCy Schubert #define M_DEFAULT "default"
49*7f2fe78bSCy Schubert
50*7f2fe78bSCy Schubert #include "k5-thread.h"
51*7f2fe78bSCy Schubert #include "k5-plugin.h"
52*7f2fe78bSCy Schubert #include "osconf.h"
53*7f2fe78bSCy Schubert #ifdef _GSS_STATIC_LINK
54*7f2fe78bSCy Schubert #include "gssapiP_krb5.h"
55*7f2fe78bSCy Schubert #include "gssapiP_spnego.h"
56*7f2fe78bSCy Schubert #endif
57*7f2fe78bSCy Schubert
58*7f2fe78bSCy Schubert #define MECH_SYM "gss_mech_initialize"
59*7f2fe78bSCy Schubert #define MECH_INTERPOSER_SYM "gss_mech_interposer"
60*7f2fe78bSCy Schubert
61*7f2fe78bSCy Schubert #ifndef MECH_CONF
62*7f2fe78bSCy Schubert #define MECH_CONF "/etc/gss/mech"
63*7f2fe78bSCy Schubert #endif
64*7f2fe78bSCy Schubert #define MECH_CONF_PATTERN MECH_CONF ".d/*.conf"
65*7f2fe78bSCy Schubert
66*7f2fe78bSCy Schubert /* Local functions */
67*7f2fe78bSCy Schubert static void addConfigEntry(const char *oidStr, const char *oid,
68*7f2fe78bSCy Schubert const char *sharedLib, const char *kernMod,
69*7f2fe78bSCy Schubert const char *modOptions, const char *modType);
70*7f2fe78bSCy Schubert static gss_mech_info searchMechList(gss_const_OID);
71*7f2fe78bSCy Schubert static void loadConfigFile(const char *);
72*7f2fe78bSCy Schubert #if defined(_WIN32)
73*7f2fe78bSCy Schubert #ifndef MECH_KEY
74*7f2fe78bSCy Schubert #define MECH_KEY "SOFTWARE\\gss\\mech"
75*7f2fe78bSCy Schubert #endif
76*7f2fe78bSCy Schubert static time_t getRegKeyModTime(HKEY hBaseKey, const char *keyPath);
77*7f2fe78bSCy Schubert static time_t getRegConfigModTime(const char *keyPath);
78*7f2fe78bSCy Schubert static void getRegKeyValue(HKEY key, const char *keyPath, const char *valueName, void **data, DWORD *dataLen);
79*7f2fe78bSCy Schubert static void loadConfigFromRegistry(HKEY keyBase, const char *keyPath);
80*7f2fe78bSCy Schubert #endif
81*7f2fe78bSCy Schubert static void updateMechList(void);
82*7f2fe78bSCy Schubert static void initMechList(void);
83*7f2fe78bSCy Schubert static void loadInterMech(gss_mech_info aMech);
84*7f2fe78bSCy Schubert static void freeMechList(void);
85*7f2fe78bSCy Schubert
86*7f2fe78bSCy Schubert static OM_uint32 build_mechSet(void);
87*7f2fe78bSCy Schubert static void free_mechSet(void);
88*7f2fe78bSCy Schubert
89*7f2fe78bSCy Schubert /*
90*7f2fe78bSCy Schubert * list of mechanism libraries and their entry points.
91*7f2fe78bSCy Schubert * the list also maintains state of the mech libraries (loaded or not).
92*7f2fe78bSCy Schubert */
93*7f2fe78bSCy Schubert static gss_mech_info g_mechList = NULL;
94*7f2fe78bSCy Schubert static gss_mech_info g_mechListTail = NULL;
95*7f2fe78bSCy Schubert static k5_mutex_t g_mechListLock = K5_MUTEX_PARTIAL_INITIALIZER;
96*7f2fe78bSCy Schubert static time_t g_confFileModTime = (time_t)-1;
97*7f2fe78bSCy Schubert static time_t g_confLastCall = (time_t)0;
98*7f2fe78bSCy Schubert
99*7f2fe78bSCy Schubert static gss_OID_set_desc g_mechSet = { 0, NULL };
100*7f2fe78bSCy Schubert static k5_mutex_t g_mechSetLock = K5_MUTEX_PARTIAL_INITIALIZER;
101*7f2fe78bSCy Schubert
102*7f2fe78bSCy Schubert MAKE_INIT_FUNCTION(gssint_mechglue_init);
103*7f2fe78bSCy Schubert MAKE_FINI_FUNCTION(gssint_mechglue_fini);
104*7f2fe78bSCy Schubert
105*7f2fe78bSCy Schubert int
gssint_mechglue_init(void)106*7f2fe78bSCy Schubert gssint_mechglue_init(void)
107*7f2fe78bSCy Schubert {
108*7f2fe78bSCy Schubert int err;
109*7f2fe78bSCy Schubert
110*7f2fe78bSCy Schubert #ifdef SHOW_INITFINI_FUNCS
111*7f2fe78bSCy Schubert printf("gssint_mechglue_init\n");
112*7f2fe78bSCy Schubert #endif
113*7f2fe78bSCy Schubert
114*7f2fe78bSCy Schubert add_error_table(&et_ggss_error_table);
115*7f2fe78bSCy Schubert
116*7f2fe78bSCy Schubert err = k5_mutex_finish_init(&g_mechSetLock);
117*7f2fe78bSCy Schubert if (err)
118*7f2fe78bSCy Schubert return err;
119*7f2fe78bSCy Schubert err = k5_mutex_finish_init(&g_mechListLock);
120*7f2fe78bSCy Schubert if (err)
121*7f2fe78bSCy Schubert return err;
122*7f2fe78bSCy Schubert
123*7f2fe78bSCy Schubert #ifdef _GSS_STATIC_LINK
124*7f2fe78bSCy Schubert err = gss_krb5int_lib_init();
125*7f2fe78bSCy Schubert if (err)
126*7f2fe78bSCy Schubert return err;
127*7f2fe78bSCy Schubert err = gss_spnegoint_lib_init();
128*7f2fe78bSCy Schubert if (err)
129*7f2fe78bSCy Schubert return err;
130*7f2fe78bSCy Schubert #endif
131*7f2fe78bSCy Schubert
132*7f2fe78bSCy Schubert err = gssint_mecherrmap_init();
133*7f2fe78bSCy Schubert return err;
134*7f2fe78bSCy Schubert }
135*7f2fe78bSCy Schubert
136*7f2fe78bSCy Schubert void
gssint_mechglue_fini(void)137*7f2fe78bSCy Schubert gssint_mechglue_fini(void)
138*7f2fe78bSCy Schubert {
139*7f2fe78bSCy Schubert if (!INITIALIZER_RAN(gssint_mechglue_init) || PROGRAM_EXITING()) {
140*7f2fe78bSCy Schubert #ifdef SHOW_INITFINI_FUNCS
141*7f2fe78bSCy Schubert printf("gssint_mechglue_fini: skipping\n");
142*7f2fe78bSCy Schubert #endif
143*7f2fe78bSCy Schubert return;
144*7f2fe78bSCy Schubert }
145*7f2fe78bSCy Schubert
146*7f2fe78bSCy Schubert #ifdef SHOW_INITFINI_FUNCS
147*7f2fe78bSCy Schubert printf("gssint_mechglue_fini\n");
148*7f2fe78bSCy Schubert #endif
149*7f2fe78bSCy Schubert #ifdef _GSS_STATIC_LINK
150*7f2fe78bSCy Schubert gss_spnegoint_lib_fini();
151*7f2fe78bSCy Schubert gss_krb5int_lib_fini();
152*7f2fe78bSCy Schubert #endif
153*7f2fe78bSCy Schubert k5_mutex_destroy(&g_mechSetLock);
154*7f2fe78bSCy Schubert k5_mutex_destroy(&g_mechListLock);
155*7f2fe78bSCy Schubert free_mechSet();
156*7f2fe78bSCy Schubert freeMechList();
157*7f2fe78bSCy Schubert remove_error_table(&et_ggss_error_table);
158*7f2fe78bSCy Schubert gssint_mecherrmap_destroy();
159*7f2fe78bSCy Schubert }
160*7f2fe78bSCy Schubert
161*7f2fe78bSCy Schubert int
gssint_mechglue_initialize_library(void)162*7f2fe78bSCy Schubert gssint_mechglue_initialize_library(void)
163*7f2fe78bSCy Schubert {
164*7f2fe78bSCy Schubert return CALL_INIT_FUNCTION(gssint_mechglue_init);
165*7f2fe78bSCy Schubert }
166*7f2fe78bSCy Schubert
167*7f2fe78bSCy Schubert /*
168*7f2fe78bSCy Schubert * function used to reclaim the memory used by a gss_OID structure.
169*7f2fe78bSCy Schubert * This routine requires direct access to the mechList.
170*7f2fe78bSCy Schubert */
171*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_release_oid(minor_status,oid)172*7f2fe78bSCy Schubert gss_release_oid(minor_status, oid)
173*7f2fe78bSCy Schubert OM_uint32 *minor_status;
174*7f2fe78bSCy Schubert gss_OID *oid;
175*7f2fe78bSCy Schubert {
176*7f2fe78bSCy Schubert OM_uint32 major;
177*7f2fe78bSCy Schubert gss_mech_info aMech;
178*7f2fe78bSCy Schubert
179*7f2fe78bSCy Schubert if (minor_status != NULL)
180*7f2fe78bSCy Schubert *minor_status = 0;
181*7f2fe78bSCy Schubert
182*7f2fe78bSCy Schubert if (minor_status == NULL || oid == NULL)
183*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_WRITE);
184*7f2fe78bSCy Schubert
185*7f2fe78bSCy Schubert *minor_status = gssint_mechglue_initialize_library();
186*7f2fe78bSCy Schubert if (*minor_status != 0)
187*7f2fe78bSCy Schubert return (GSS_S_FAILURE);
188*7f2fe78bSCy Schubert
189*7f2fe78bSCy Schubert k5_mutex_lock(&g_mechListLock);
190*7f2fe78bSCy Schubert aMech = g_mechList;
191*7f2fe78bSCy Schubert while (aMech != NULL) {
192*7f2fe78bSCy Schubert
193*7f2fe78bSCy Schubert /*
194*7f2fe78bSCy Schubert * look through the loaded mechanism libraries for
195*7f2fe78bSCy Schubert * gss_internal_release_oid until one returns success.
196*7f2fe78bSCy Schubert * gss_internal_release_oid will only return success when
197*7f2fe78bSCy Schubert * the OID was recognized as an internal mechanism OID. if no
198*7f2fe78bSCy Schubert * mechanisms recognize the OID, then call the generic version.
199*7f2fe78bSCy Schubert */
200*7f2fe78bSCy Schubert if (aMech->mech && aMech->mech->gss_internal_release_oid) {
201*7f2fe78bSCy Schubert major = aMech->mech->gss_internal_release_oid(
202*7f2fe78bSCy Schubert minor_status, oid);
203*7f2fe78bSCy Schubert if (major == GSS_S_COMPLETE) {
204*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
205*7f2fe78bSCy Schubert return (GSS_S_COMPLETE);
206*7f2fe78bSCy Schubert }
207*7f2fe78bSCy Schubert map_error(minor_status, aMech->mech);
208*7f2fe78bSCy Schubert }
209*7f2fe78bSCy Schubert aMech = aMech->next;
210*7f2fe78bSCy Schubert } /* while */
211*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
212*7f2fe78bSCy Schubert
213*7f2fe78bSCy Schubert return (generic_gss_release_oid(minor_status, oid));
214*7f2fe78bSCy Schubert } /* gss_release_oid */
215*7f2fe78bSCy Schubert
216*7f2fe78bSCy Schubert /*
217*7f2fe78bSCy Schubert * Wrapper around inquire_attrs_for_mech to determine whether a mechanism has
218*7f2fe78bSCy Schubert * the deprecated attribute. Must be called without g_mechSetLock since it
219*7f2fe78bSCy Schubert * will call into the mechglue.
220*7f2fe78bSCy Schubert */
221*7f2fe78bSCy Schubert static int
is_deprecated(gss_OID element)222*7f2fe78bSCy Schubert is_deprecated(gss_OID element)
223*7f2fe78bSCy Schubert {
224*7f2fe78bSCy Schubert OM_uint32 major, minor;
225*7f2fe78bSCy Schubert gss_OID_set mech_attrs = GSS_C_NO_OID_SET;
226*7f2fe78bSCy Schubert int deprecated = 0;
227*7f2fe78bSCy Schubert
228*7f2fe78bSCy Schubert major = gss_inquire_attrs_for_mech(&minor, element, &mech_attrs, NULL);
229*7f2fe78bSCy Schubert if (major == GSS_S_COMPLETE) {
230*7f2fe78bSCy Schubert gss_test_oid_set_member(&minor, (gss_OID)GSS_C_MA_DEPRECATED,
231*7f2fe78bSCy Schubert mech_attrs, &deprecated);
232*7f2fe78bSCy Schubert }
233*7f2fe78bSCy Schubert
234*7f2fe78bSCy Schubert if (mech_attrs != GSS_C_NO_OID_SET)
235*7f2fe78bSCy Schubert gss_release_oid_set(&minor, &mech_attrs);
236*7f2fe78bSCy Schubert
237*7f2fe78bSCy Schubert return deprecated;
238*7f2fe78bSCy Schubert }
239*7f2fe78bSCy Schubert
240*7f2fe78bSCy Schubert /*
241*7f2fe78bSCy Schubert * Removes mechs with the deprecated attribute from an OID set. Must be
242*7f2fe78bSCy Schubert * called without g_mechSetLock held since it calls into the mechglue.
243*7f2fe78bSCy Schubert */
244*7f2fe78bSCy Schubert static void
prune_deprecated(gss_OID_set mech_set)245*7f2fe78bSCy Schubert prune_deprecated(gss_OID_set mech_set)
246*7f2fe78bSCy Schubert {
247*7f2fe78bSCy Schubert OM_uint32 i, j;
248*7f2fe78bSCy Schubert
249*7f2fe78bSCy Schubert j = 0;
250*7f2fe78bSCy Schubert for (i = 0; i < mech_set->count; i++) {
251*7f2fe78bSCy Schubert if (!is_deprecated(&mech_set->elements[i]))
252*7f2fe78bSCy Schubert mech_set->elements[j++] = mech_set->elements[i];
253*7f2fe78bSCy Schubert else
254*7f2fe78bSCy Schubert gssalloc_free(mech_set->elements[i].elements);
255*7f2fe78bSCy Schubert }
256*7f2fe78bSCy Schubert mech_set->count = j;
257*7f2fe78bSCy Schubert }
258*7f2fe78bSCy Schubert
259*7f2fe78bSCy Schubert /*
260*7f2fe78bSCy Schubert * this function will return an oid set indicating available mechanisms.
261*7f2fe78bSCy Schubert * The set returned is based on configuration file entries and
262*7f2fe78bSCy Schubert * NOT on the loaded mechanisms. This function does not check if any
263*7f2fe78bSCy Schubert * of these can actually be loaded.
264*7f2fe78bSCy Schubert * Deprecated mechanisms will not be returned.
265*7f2fe78bSCy Schubert * This routine needs direct access to the mechanism list.
266*7f2fe78bSCy Schubert * To avoid reading the configuration file each call, we will save a
267*7f2fe78bSCy Schubert * a mech oid set, and only update it once the file has changed.
268*7f2fe78bSCy Schubert */
269*7f2fe78bSCy Schubert OM_uint32 KRB5_CALLCONV
gss_indicate_mechs(minorStatus,mechSet_out)270*7f2fe78bSCy Schubert gss_indicate_mechs(minorStatus, mechSet_out)
271*7f2fe78bSCy Schubert OM_uint32 *minorStatus;
272*7f2fe78bSCy Schubert gss_OID_set *mechSet_out;
273*7f2fe78bSCy Schubert {
274*7f2fe78bSCy Schubert OM_uint32 status;
275*7f2fe78bSCy Schubert
276*7f2fe78bSCy Schubert /* Initialize outputs. */
277*7f2fe78bSCy Schubert
278*7f2fe78bSCy Schubert if (minorStatus != NULL)
279*7f2fe78bSCy Schubert *minorStatus = 0;
280*7f2fe78bSCy Schubert
281*7f2fe78bSCy Schubert if (mechSet_out != NULL)
282*7f2fe78bSCy Schubert *mechSet_out = GSS_C_NO_OID_SET;
283*7f2fe78bSCy Schubert
284*7f2fe78bSCy Schubert /* Validate arguments. */
285*7f2fe78bSCy Schubert if (minorStatus == NULL || mechSet_out == NULL)
286*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_WRITE);
287*7f2fe78bSCy Schubert
288*7f2fe78bSCy Schubert *minorStatus = gssint_mechglue_initialize_library();
289*7f2fe78bSCy Schubert if (*minorStatus != 0)
290*7f2fe78bSCy Schubert return (GSS_S_FAILURE);
291*7f2fe78bSCy Schubert
292*7f2fe78bSCy Schubert if (build_mechSet())
293*7f2fe78bSCy Schubert return GSS_S_FAILURE;
294*7f2fe78bSCy Schubert
295*7f2fe78bSCy Schubert /*
296*7f2fe78bSCy Schubert * need to lock the g_mechSet in case someone tries to update it while
297*7f2fe78bSCy Schubert * I'm copying it.
298*7f2fe78bSCy Schubert */
299*7f2fe78bSCy Schubert k5_mutex_lock(&g_mechSetLock);
300*7f2fe78bSCy Schubert status = generic_gss_copy_oid_set(minorStatus, &g_mechSet, mechSet_out);
301*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechSetLock);
302*7f2fe78bSCy Schubert
303*7f2fe78bSCy Schubert if (*mechSet_out != GSS_C_NO_OID_SET)
304*7f2fe78bSCy Schubert prune_deprecated(*mechSet_out);
305*7f2fe78bSCy Schubert
306*7f2fe78bSCy Schubert return (status);
307*7f2fe78bSCy Schubert } /* gss_indicate_mechs */
308*7f2fe78bSCy Schubert
309*7f2fe78bSCy Schubert
310*7f2fe78bSCy Schubert /* Call with g_mechSetLock held, or during final cleanup. */
311*7f2fe78bSCy Schubert static void
free_mechSet(void)312*7f2fe78bSCy Schubert free_mechSet(void)
313*7f2fe78bSCy Schubert {
314*7f2fe78bSCy Schubert unsigned int i;
315*7f2fe78bSCy Schubert
316*7f2fe78bSCy Schubert if (g_mechSet.count != 0) {
317*7f2fe78bSCy Schubert for (i = 0; i < g_mechSet.count; i++)
318*7f2fe78bSCy Schubert free(g_mechSet.elements[i].elements);
319*7f2fe78bSCy Schubert free(g_mechSet.elements);
320*7f2fe78bSCy Schubert g_mechSet.elements = NULL;
321*7f2fe78bSCy Schubert g_mechSet.count = 0;
322*7f2fe78bSCy Schubert }
323*7f2fe78bSCy Schubert }
324*7f2fe78bSCy Schubert
325*7f2fe78bSCy Schubert static OM_uint32
build_mechSet(void)326*7f2fe78bSCy Schubert build_mechSet(void)
327*7f2fe78bSCy Schubert {
328*7f2fe78bSCy Schubert gss_mech_info mList;
329*7f2fe78bSCy Schubert size_t i;
330*7f2fe78bSCy Schubert size_t count;
331*7f2fe78bSCy Schubert gss_OID curItem;
332*7f2fe78bSCy Schubert
333*7f2fe78bSCy Schubert /*
334*7f2fe78bSCy Schubert * lock the mutex since we will be updating
335*7f2fe78bSCy Schubert * the mechList structure
336*7f2fe78bSCy Schubert * we need to keep the lock while we build the mechanism list
337*7f2fe78bSCy Schubert * since we are accessing parts of the mechList which could be
338*7f2fe78bSCy Schubert * modified.
339*7f2fe78bSCy Schubert */
340*7f2fe78bSCy Schubert k5_mutex_lock(&g_mechListLock);
341*7f2fe78bSCy Schubert
342*7f2fe78bSCy Schubert updateMechList();
343*7f2fe78bSCy Schubert
344*7f2fe78bSCy Schubert /*
345*7f2fe78bSCy Schubert * we need to lock the mech set so that no one else will
346*7f2fe78bSCy Schubert * try to read it as we are re-creating it
347*7f2fe78bSCy Schubert */
348*7f2fe78bSCy Schubert k5_mutex_lock(&g_mechSetLock);
349*7f2fe78bSCy Schubert
350*7f2fe78bSCy Schubert /* if the oid list already exists we must free it first */
351*7f2fe78bSCy Schubert free_mechSet();
352*7f2fe78bSCy Schubert
353*7f2fe78bSCy Schubert /* determine how many elements to have in the list */
354*7f2fe78bSCy Schubert mList = g_mechList;
355*7f2fe78bSCy Schubert count = 0;
356*7f2fe78bSCy Schubert while (mList != NULL) {
357*7f2fe78bSCy Schubert count++;
358*7f2fe78bSCy Schubert mList = mList->next;
359*7f2fe78bSCy Schubert }
360*7f2fe78bSCy Schubert
361*7f2fe78bSCy Schubert /* this should always be true, but.... */
362*7f2fe78bSCy Schubert if (count > 0) {
363*7f2fe78bSCy Schubert g_mechSet.elements =
364*7f2fe78bSCy Schubert (gss_OID) calloc(count, sizeof (gss_OID_desc));
365*7f2fe78bSCy Schubert if (g_mechSet.elements == NULL) {
366*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechSetLock);
367*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
368*7f2fe78bSCy Schubert return (GSS_S_FAILURE);
369*7f2fe78bSCy Schubert }
370*7f2fe78bSCy Schubert
371*7f2fe78bSCy Schubert (void) memset(g_mechSet.elements, 0,
372*7f2fe78bSCy Schubert count * sizeof (gss_OID_desc));
373*7f2fe78bSCy Schubert
374*7f2fe78bSCy Schubert /* now copy each oid element */
375*7f2fe78bSCy Schubert count = 0;
376*7f2fe78bSCy Schubert for (mList = g_mechList; mList != NULL; mList = mList->next) {
377*7f2fe78bSCy Schubert /* Don't expose interposer mechanisms. */
378*7f2fe78bSCy Schubert if (mList->is_interposer)
379*7f2fe78bSCy Schubert continue;
380*7f2fe78bSCy Schubert curItem = &(g_mechSet.elements[count]);
381*7f2fe78bSCy Schubert curItem->elements = (void*)
382*7f2fe78bSCy Schubert malloc(mList->mech_type->length);
383*7f2fe78bSCy Schubert if (curItem->elements == NULL) {
384*7f2fe78bSCy Schubert /*
385*7f2fe78bSCy Schubert * this is nasty - we must delete the
386*7f2fe78bSCy Schubert * part of the array already copied
387*7f2fe78bSCy Schubert */
388*7f2fe78bSCy Schubert for (i = 0; i < count; i++) {
389*7f2fe78bSCy Schubert free(g_mechSet.elements[i].
390*7f2fe78bSCy Schubert elements);
391*7f2fe78bSCy Schubert }
392*7f2fe78bSCy Schubert free(g_mechSet.elements);
393*7f2fe78bSCy Schubert g_mechSet.count = 0;
394*7f2fe78bSCy Schubert g_mechSet.elements = NULL;
395*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechSetLock);
396*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
397*7f2fe78bSCy Schubert return (GSS_S_FAILURE);
398*7f2fe78bSCy Schubert }
399*7f2fe78bSCy Schubert g_OID_copy(curItem, mList->mech_type);
400*7f2fe78bSCy Schubert count++;
401*7f2fe78bSCy Schubert }
402*7f2fe78bSCy Schubert g_mechSet.count = count;
403*7f2fe78bSCy Schubert }
404*7f2fe78bSCy Schubert
405*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechSetLock);
406*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
407*7f2fe78bSCy Schubert
408*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
409*7f2fe78bSCy Schubert }
410*7f2fe78bSCy Schubert
411*7f2fe78bSCy Schubert
412*7f2fe78bSCy Schubert /*
413*7f2fe78bSCy Schubert * this function has been added for use by modules that need to
414*7f2fe78bSCy Schubert * know what (if any) optional parameters are supplied in the
415*7f2fe78bSCy Schubert * config file (MECH_CONF).
416*7f2fe78bSCy Schubert * It will return the option string for a specified mechanism.
417*7f2fe78bSCy Schubert * caller is responsible for freeing the memory
418*7f2fe78bSCy Schubert */
419*7f2fe78bSCy Schubert char *
gssint_get_modOptions(oid)420*7f2fe78bSCy Schubert gssint_get_modOptions(oid)
421*7f2fe78bSCy Schubert const gss_OID oid;
422*7f2fe78bSCy Schubert {
423*7f2fe78bSCy Schubert gss_mech_info aMech;
424*7f2fe78bSCy Schubert char *modOptions = NULL;
425*7f2fe78bSCy Schubert
426*7f2fe78bSCy Schubert if (gssint_mechglue_initialize_library() != 0)
427*7f2fe78bSCy Schubert return (NULL);
428*7f2fe78bSCy Schubert
429*7f2fe78bSCy Schubert /* make sure we have fresh data */
430*7f2fe78bSCy Schubert k5_mutex_lock(&g_mechListLock);
431*7f2fe78bSCy Schubert updateMechList();
432*7f2fe78bSCy Schubert
433*7f2fe78bSCy Schubert if ((aMech = searchMechList(oid)) == NULL ||
434*7f2fe78bSCy Schubert aMech->optionStr == NULL) {
435*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
436*7f2fe78bSCy Schubert return (NULL);
437*7f2fe78bSCy Schubert }
438*7f2fe78bSCy Schubert
439*7f2fe78bSCy Schubert if (aMech->optionStr)
440*7f2fe78bSCy Schubert modOptions = strdup(aMech->optionStr);
441*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
442*7f2fe78bSCy Schubert
443*7f2fe78bSCy Schubert return (modOptions);
444*7f2fe78bSCy Schubert } /* gssint_get_modOptions */
445*7f2fe78bSCy Schubert
446*7f2fe78bSCy Schubert /* Return the mtime of filename or its eventual symlink target (if it is a
447*7f2fe78bSCy Schubert * symlink), whichever is larger. Return (time_t)-1 if lstat or stat fails. */
448*7f2fe78bSCy Schubert static time_t
check_link_mtime(const char * filename,time_t * mtime_out)449*7f2fe78bSCy Schubert check_link_mtime(const char *filename, time_t *mtime_out)
450*7f2fe78bSCy Schubert {
451*7f2fe78bSCy Schubert struct stat st1, st2;
452*7f2fe78bSCy Schubert
453*7f2fe78bSCy Schubert if (lstat(filename, &st1) != 0)
454*7f2fe78bSCy Schubert return (time_t)-1;
455*7f2fe78bSCy Schubert if (!S_ISLNK(st1.st_mode))
456*7f2fe78bSCy Schubert return st1.st_mtime;
457*7f2fe78bSCy Schubert if (stat(filename, &st2) != 0)
458*7f2fe78bSCy Schubert return (time_t)-1;
459*7f2fe78bSCy Schubert return (st1.st_mtime > st2.st_mtime) ? st1.st_mtime : st2.st_mtime;
460*7f2fe78bSCy Schubert }
461*7f2fe78bSCy Schubert
462*7f2fe78bSCy Schubert /* Load pathname if it is newer than last. Update *highest to the maximum of
463*7f2fe78bSCy Schubert * its current value and pathname's mod time. */
464*7f2fe78bSCy Schubert static void
load_if_changed(const char * pathname,time_t last,time_t * highest)465*7f2fe78bSCy Schubert load_if_changed(const char *pathname, time_t last, time_t *highest)
466*7f2fe78bSCy Schubert {
467*7f2fe78bSCy Schubert time_t mtime;
468*7f2fe78bSCy Schubert
469*7f2fe78bSCy Schubert mtime = check_link_mtime(pathname, &mtime);
470*7f2fe78bSCy Schubert if (mtime == (time_t)-1)
471*7f2fe78bSCy Schubert return;
472*7f2fe78bSCy Schubert if (mtime > *highest || *highest == (time_t)-1)
473*7f2fe78bSCy Schubert *highest = mtime;
474*7f2fe78bSCy Schubert if (mtime > last || last == (time_t)-1)
475*7f2fe78bSCy Schubert loadConfigFile(pathname);
476*7f2fe78bSCy Schubert }
477*7f2fe78bSCy Schubert
478*7f2fe78bSCy Schubert #ifndef _WIN32
479*7f2fe78bSCy Schubert /* Try to load any config files which have changed since the last call. Config
480*7f2fe78bSCy Schubert * files are MECH_CONF and any files matching MECH_CONF_PATTERN. */
481*7f2fe78bSCy Schubert static void
loadConfigFiles()482*7f2fe78bSCy Schubert loadConfigFiles()
483*7f2fe78bSCy Schubert {
484*7f2fe78bSCy Schubert glob_t globbuf;
485*7f2fe78bSCy Schubert time_t highest = (time_t)-1, now;
486*7f2fe78bSCy Schubert char **path;
487*7f2fe78bSCy Schubert const char *val;
488*7f2fe78bSCy Schubert
489*7f2fe78bSCy Schubert /* Don't glob and stat more than once per second. */
490*7f2fe78bSCy Schubert if (time(&now) == (time_t)-1 || now == g_confLastCall)
491*7f2fe78bSCy Schubert return;
492*7f2fe78bSCy Schubert g_confLastCall = now;
493*7f2fe78bSCy Schubert
494*7f2fe78bSCy Schubert val = secure_getenv("GSS_MECH_CONFIG");
495*7f2fe78bSCy Schubert if (val != NULL) {
496*7f2fe78bSCy Schubert load_if_changed(val, g_confFileModTime, &g_confFileModTime);
497*7f2fe78bSCy Schubert return;
498*7f2fe78bSCy Schubert }
499*7f2fe78bSCy Schubert
500*7f2fe78bSCy Schubert load_if_changed(MECH_CONF, g_confFileModTime, &highest);
501*7f2fe78bSCy Schubert
502*7f2fe78bSCy Schubert memset(&globbuf, 0, sizeof(globbuf));
503*7f2fe78bSCy Schubert if (glob(MECH_CONF_PATTERN, 0, NULL, &globbuf) == 0) {
504*7f2fe78bSCy Schubert for (path = globbuf.gl_pathv; *path != NULL; path++)
505*7f2fe78bSCy Schubert load_if_changed(*path, g_confFileModTime, &highest);
506*7f2fe78bSCy Schubert }
507*7f2fe78bSCy Schubert globfree(&globbuf);
508*7f2fe78bSCy Schubert
509*7f2fe78bSCy Schubert g_confFileModTime = highest;
510*7f2fe78bSCy Schubert }
511*7f2fe78bSCy Schubert #endif
512*7f2fe78bSCy Schubert
513*7f2fe78bSCy Schubert /*
514*7f2fe78bSCy Schubert * determines if the mechList needs to be updated from file
515*7f2fe78bSCy Schubert * and performs the update.
516*7f2fe78bSCy Schubert * this functions must be called with a lock of g_mechListLock
517*7f2fe78bSCy Schubert */
518*7f2fe78bSCy Schubert static void
updateMechList(void)519*7f2fe78bSCy Schubert updateMechList(void)
520*7f2fe78bSCy Schubert {
521*7f2fe78bSCy Schubert gss_mech_info minfo;
522*7f2fe78bSCy Schubert
523*7f2fe78bSCy Schubert #if defined(_WIN32)
524*7f2fe78bSCy Schubert time_t lastConfModTime = getRegConfigModTime(MECH_KEY);
525*7f2fe78bSCy Schubert if (g_confFileModTime >= lastConfModTime &&
526*7f2fe78bSCy Schubert g_confFileModTime != (time_t)-1)
527*7f2fe78bSCy Schubert return;
528*7f2fe78bSCy Schubert g_confFileModTime = lastConfModTime;
529*7f2fe78bSCy Schubert loadConfigFromRegistry(HKEY_CURRENT_USER, MECH_KEY);
530*7f2fe78bSCy Schubert loadConfigFromRegistry(HKEY_LOCAL_MACHINE, MECH_KEY);
531*7f2fe78bSCy Schubert #else /* _WIN32 */
532*7f2fe78bSCy Schubert loadConfigFiles();
533*7f2fe78bSCy Schubert #endif /* !_WIN32 */
534*7f2fe78bSCy Schubert
535*7f2fe78bSCy Schubert /* Load any unloaded interposer mechanisms immediately, to make sure we
536*7f2fe78bSCy Schubert * interpose other mechanisms before they are used. */
537*7f2fe78bSCy Schubert for (minfo = g_mechList; minfo != NULL; minfo = minfo->next) {
538*7f2fe78bSCy Schubert if (minfo->is_interposer && minfo->mech == NULL)
539*7f2fe78bSCy Schubert loadInterMech(minfo);
540*7f2fe78bSCy Schubert }
541*7f2fe78bSCy Schubert } /* updateMechList */
542*7f2fe78bSCy Schubert
543*7f2fe78bSCy Schubert /* Update the mech list from system configuration if we have never done so.
544*7f2fe78bSCy Schubert * Must be invoked with the g_mechListLock mutex held. */
545*7f2fe78bSCy Schubert static void
initMechList(void)546*7f2fe78bSCy Schubert initMechList(void)
547*7f2fe78bSCy Schubert {
548*7f2fe78bSCy Schubert static int lazy_init = 0;
549*7f2fe78bSCy Schubert
550*7f2fe78bSCy Schubert if (lazy_init == 0) {
551*7f2fe78bSCy Schubert updateMechList();
552*7f2fe78bSCy Schubert lazy_init = 1;
553*7f2fe78bSCy Schubert }
554*7f2fe78bSCy Schubert }
555*7f2fe78bSCy Schubert
556*7f2fe78bSCy Schubert static void
releaseMechInfo(gss_mech_info * pCf)557*7f2fe78bSCy Schubert releaseMechInfo(gss_mech_info *pCf)
558*7f2fe78bSCy Schubert {
559*7f2fe78bSCy Schubert gss_mech_info cf;
560*7f2fe78bSCy Schubert OM_uint32 minor_status;
561*7f2fe78bSCy Schubert
562*7f2fe78bSCy Schubert if (*pCf == NULL) {
563*7f2fe78bSCy Schubert return;
564*7f2fe78bSCy Schubert }
565*7f2fe78bSCy Schubert
566*7f2fe78bSCy Schubert cf = *pCf;
567*7f2fe78bSCy Schubert
568*7f2fe78bSCy Schubert if (cf->kmodName != NULL)
569*7f2fe78bSCy Schubert free(cf->kmodName);
570*7f2fe78bSCy Schubert if (cf->uLibName != NULL)
571*7f2fe78bSCy Schubert free(cf->uLibName);
572*7f2fe78bSCy Schubert if (cf->mechNameStr != NULL)
573*7f2fe78bSCy Schubert free(cf->mechNameStr);
574*7f2fe78bSCy Schubert if (cf->optionStr != NULL)
575*7f2fe78bSCy Schubert free(cf->optionStr);
576*7f2fe78bSCy Schubert if (cf->mech_type != GSS_C_NO_OID &&
577*7f2fe78bSCy Schubert cf->mech_type != &cf->mech->mech_type)
578*7f2fe78bSCy Schubert generic_gss_release_oid(&minor_status, &cf->mech_type);
579*7f2fe78bSCy Schubert if (cf->freeMech)
580*7f2fe78bSCy Schubert zapfree(cf->mech, sizeof(*cf->mech));
581*7f2fe78bSCy Schubert if (cf->dl_handle != NULL)
582*7f2fe78bSCy Schubert krb5int_close_plugin(cf->dl_handle);
583*7f2fe78bSCy Schubert if (cf->int_mech_type != GSS_C_NO_OID)
584*7f2fe78bSCy Schubert generic_gss_release_oid(&minor_status, &cf->int_mech_type);
585*7f2fe78bSCy Schubert
586*7f2fe78bSCy Schubert memset(cf, 0, sizeof(*cf));
587*7f2fe78bSCy Schubert free(cf);
588*7f2fe78bSCy Schubert
589*7f2fe78bSCy Schubert *pCf = NULL;
590*7f2fe78bSCy Schubert }
591*7f2fe78bSCy Schubert
592*7f2fe78bSCy Schubert #ifdef _GSS_STATIC_LINK
593*7f2fe78bSCy Schubert /*
594*7f2fe78bSCy Schubert * Register a mechanism. Called with g_mechListLock held.
595*7f2fe78bSCy Schubert */
596*7f2fe78bSCy Schubert int
gssint_register_mechinfo(gss_mech_info template)597*7f2fe78bSCy Schubert gssint_register_mechinfo(gss_mech_info template)
598*7f2fe78bSCy Schubert {
599*7f2fe78bSCy Schubert gss_mech_info cf, new_cf;
600*7f2fe78bSCy Schubert
601*7f2fe78bSCy Schubert new_cf = calloc(1, sizeof(*new_cf));
602*7f2fe78bSCy Schubert if (new_cf == NULL) {
603*7f2fe78bSCy Schubert return ENOMEM;
604*7f2fe78bSCy Schubert }
605*7f2fe78bSCy Schubert
606*7f2fe78bSCy Schubert new_cf->dl_handle = template->dl_handle;
607*7f2fe78bSCy Schubert /* copy mech so we can rewrite canonical mechanism OID */
608*7f2fe78bSCy Schubert new_cf->mech = (gss_mechanism)calloc(1, sizeof(struct gss_config));
609*7f2fe78bSCy Schubert if (new_cf->mech == NULL) {
610*7f2fe78bSCy Schubert releaseMechInfo(&new_cf);
611*7f2fe78bSCy Schubert return ENOMEM;
612*7f2fe78bSCy Schubert }
613*7f2fe78bSCy Schubert *new_cf->mech = *template->mech;
614*7f2fe78bSCy Schubert if (template->mech_type != NULL)
615*7f2fe78bSCy Schubert new_cf->mech->mech_type = *(template->mech_type);
616*7f2fe78bSCy Schubert new_cf->mech_type = &new_cf->mech->mech_type;
617*7f2fe78bSCy Schubert new_cf->priority = template->priority;
618*7f2fe78bSCy Schubert new_cf->freeMech = 1;
619*7f2fe78bSCy Schubert new_cf->next = NULL;
620*7f2fe78bSCy Schubert
621*7f2fe78bSCy Schubert if (template->kmodName != NULL) {
622*7f2fe78bSCy Schubert new_cf->kmodName = strdup(template->kmodName);
623*7f2fe78bSCy Schubert if (new_cf->kmodName == NULL) {
624*7f2fe78bSCy Schubert releaseMechInfo(&new_cf);
625*7f2fe78bSCy Schubert return ENOMEM;
626*7f2fe78bSCy Schubert }
627*7f2fe78bSCy Schubert }
628*7f2fe78bSCy Schubert if (template->uLibName != NULL) {
629*7f2fe78bSCy Schubert new_cf->uLibName = strdup(template->uLibName);
630*7f2fe78bSCy Schubert if (new_cf->uLibName == NULL) {
631*7f2fe78bSCy Schubert releaseMechInfo(&new_cf);
632*7f2fe78bSCy Schubert return ENOMEM;
633*7f2fe78bSCy Schubert }
634*7f2fe78bSCy Schubert }
635*7f2fe78bSCy Schubert if (template->mechNameStr != NULL) {
636*7f2fe78bSCy Schubert new_cf->mechNameStr = strdup(template->mechNameStr);
637*7f2fe78bSCy Schubert if (new_cf->mechNameStr == NULL) {
638*7f2fe78bSCy Schubert releaseMechInfo(&new_cf);
639*7f2fe78bSCy Schubert return ENOMEM;
640*7f2fe78bSCy Schubert }
641*7f2fe78bSCy Schubert }
642*7f2fe78bSCy Schubert if (template->optionStr != NULL) {
643*7f2fe78bSCy Schubert new_cf->optionStr = strdup(template->optionStr);
644*7f2fe78bSCy Schubert if (new_cf->optionStr == NULL) {
645*7f2fe78bSCy Schubert releaseMechInfo(&new_cf);
646*7f2fe78bSCy Schubert return ENOMEM;
647*7f2fe78bSCy Schubert }
648*7f2fe78bSCy Schubert }
649*7f2fe78bSCy Schubert if (g_mechList == NULL) {
650*7f2fe78bSCy Schubert g_mechList = new_cf;
651*7f2fe78bSCy Schubert g_mechListTail = new_cf;
652*7f2fe78bSCy Schubert return 0;
653*7f2fe78bSCy Schubert } else if (new_cf->priority < g_mechList->priority) {
654*7f2fe78bSCy Schubert new_cf->next = g_mechList;
655*7f2fe78bSCy Schubert g_mechList = new_cf;
656*7f2fe78bSCy Schubert return 0;
657*7f2fe78bSCy Schubert }
658*7f2fe78bSCy Schubert
659*7f2fe78bSCy Schubert for (cf = g_mechList; cf != NULL; cf = cf->next) {
660*7f2fe78bSCy Schubert if (cf->next == NULL ||
661*7f2fe78bSCy Schubert new_cf->priority < cf->next->priority) {
662*7f2fe78bSCy Schubert new_cf->next = cf->next;
663*7f2fe78bSCy Schubert cf->next = new_cf;
664*7f2fe78bSCy Schubert if (g_mechListTail == cf) {
665*7f2fe78bSCy Schubert g_mechListTail = new_cf;
666*7f2fe78bSCy Schubert }
667*7f2fe78bSCy Schubert break;
668*7f2fe78bSCy Schubert }
669*7f2fe78bSCy Schubert }
670*7f2fe78bSCy Schubert
671*7f2fe78bSCy Schubert return 0;
672*7f2fe78bSCy Schubert }
673*7f2fe78bSCy Schubert #endif /* _GSS_STATIC_LINK */
674*7f2fe78bSCy Schubert
675*7f2fe78bSCy Schubert #define GSS_ADD_DYNAMIC_METHOD(_dl, _mech, _symbol) \
676*7f2fe78bSCy Schubert do { \
677*7f2fe78bSCy Schubert struct errinfo errinfo; \
678*7f2fe78bSCy Schubert \
679*7f2fe78bSCy Schubert memset(&errinfo, 0, sizeof(errinfo)); \
680*7f2fe78bSCy Schubert if (krb5int_get_plugin_func(_dl, \
681*7f2fe78bSCy Schubert #_symbol, \
682*7f2fe78bSCy Schubert (void (**)())&(_mech)->_symbol, \
683*7f2fe78bSCy Schubert &errinfo) || errinfo.code) { \
684*7f2fe78bSCy Schubert (_mech)->_symbol = NULL; \
685*7f2fe78bSCy Schubert k5_clear_error(&errinfo); \
686*7f2fe78bSCy Schubert } \
687*7f2fe78bSCy Schubert } while (0)
688*7f2fe78bSCy Schubert
689*7f2fe78bSCy Schubert /*
690*7f2fe78bSCy Schubert * If _symbol is undefined in the shared object but the shared object
691*7f2fe78bSCy Schubert * is linked against the mechanism glue, it's possible for dlsym() to
692*7f2fe78bSCy Schubert * return the mechanism glue implementation. Guard against that.
693*7f2fe78bSCy Schubert */
694*7f2fe78bSCy Schubert #define GSS_ADD_DYNAMIC_METHOD_NOLOOP(_dl, _mech, _symbol) \
695*7f2fe78bSCy Schubert do { \
696*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD(_dl, _mech, _symbol); \
697*7f2fe78bSCy Schubert if ((_mech)->_symbol == _symbol) \
698*7f2fe78bSCy Schubert (_mech)->_symbol = NULL; \
699*7f2fe78bSCy Schubert } while (0)
700*7f2fe78bSCy Schubert
701*7f2fe78bSCy Schubert static gss_mechanism
build_dynamicMech(void * dl,const gss_OID mech_type)702*7f2fe78bSCy Schubert build_dynamicMech(void *dl, const gss_OID mech_type)
703*7f2fe78bSCy Schubert {
704*7f2fe78bSCy Schubert gss_mechanism mech;
705*7f2fe78bSCy Schubert
706*7f2fe78bSCy Schubert mech = (gss_mechanism)calloc(1, sizeof(*mech));
707*7f2fe78bSCy Schubert if (mech == NULL) {
708*7f2fe78bSCy Schubert return NULL;
709*7f2fe78bSCy Schubert }
710*7f2fe78bSCy Schubert
711*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_acquire_cred);
712*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_release_cred);
713*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_init_sec_context);
714*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_accept_sec_context);
715*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_process_context_token);
716*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_delete_sec_context);
717*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_context_time);
718*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_get_mic);
719*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_verify_mic);
720*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap);
721*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_unwrap);
722*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_display_status);
723*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_indicate_mechs);
724*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_compare_name);
725*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_display_name);
726*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_import_name);
727*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_release_name);
728*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_cred);
729*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_add_cred);
730*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_sec_context);
731*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_import_sec_context);
732*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_cred_by_mech);
733*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_names_for_mech);
734*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_context);
735*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_internal_release_oid);
736*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_size_limit);
737*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_localname);
738*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_authorize_localname);
739*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_name);
740*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_duplicate_name);
741*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_store_cred);
742*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_sec_context_by_oid);
743*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_cred_by_oid);
744*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_set_sec_context_option);
745*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_set_cred_option);
746*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gssspi_mech_invoke);
747*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_aead);
748*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_unwrap_aead);
749*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_iov);
750*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_unwrap_iov);
751*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_iov_length);
752*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_complete_auth_token);
753*7f2fe78bSCy Schubert /* Services4User (introduced in 1.8) */
754*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_acquire_cred_impersonate_name);
755*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_add_cred_impersonate_name);
756*7f2fe78bSCy Schubert /* Naming extensions (introduced in 1.8) */
757*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_display_name_ext);
758*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_name);
759*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_get_name_attribute);
760*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_set_name_attribute);
761*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_delete_name_attribute);
762*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_name_composite);
763*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_map_name_to_any);
764*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_release_any_name_mapping);
765*7f2fe78bSCy Schubert /* RFC 4401 (introduced in 1.8) */
766*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_pseudo_random);
767*7f2fe78bSCy Schubert /* RFC 4178 (introduced in 1.8; gss_get_neg_mechs not implemented) */
768*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_set_neg_mechs);
769*7f2fe78bSCy Schubert /* draft-ietf-sasl-gs2 */
770*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_saslname_for_mech);
771*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_mech_for_saslname);
772*7f2fe78bSCy Schubert /* RFC 5587 */
773*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_attrs_for_mech);
774*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_acquire_cred_from);
775*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_store_cred_into);
776*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_acquire_cred_with_password);
777*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_cred);
778*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_import_cred);
779*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_sec_context_by_mech);
780*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_name_by_mech);
781*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_cred_by_mech);
782*7f2fe78bSCy Schubert /* draft-zhu-negoex */
783*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gssspi_query_meta_data);
784*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gssspi_exchange_meta_data);
785*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gssspi_query_mechanism_info);
786*7f2fe78bSCy Schubert /* gss_get_mic_iov extensions (added 1.12, implementable 1.20) */
787*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_get_mic_iov);
788*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_verify_mic_iov);
789*7f2fe78bSCy Schubert GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_get_mic_iov_length);
790*7f2fe78bSCy Schubert
791*7f2fe78bSCy Schubert assert(mech_type != GSS_C_NO_OID);
792*7f2fe78bSCy Schubert
793*7f2fe78bSCy Schubert mech->mech_type = *(mech_type);
794*7f2fe78bSCy Schubert
795*7f2fe78bSCy Schubert return mech;
796*7f2fe78bSCy Schubert }
797*7f2fe78bSCy Schubert
798*7f2fe78bSCy Schubert #define RESOLVE_GSSI_SYMBOL(_dl, _mech, _psym, _nsym) \
799*7f2fe78bSCy Schubert do { \
800*7f2fe78bSCy Schubert struct errinfo errinfo; \
801*7f2fe78bSCy Schubert memset(&errinfo, 0, sizeof(errinfo)); \
802*7f2fe78bSCy Schubert if (krb5int_get_plugin_func(_dl, \
803*7f2fe78bSCy Schubert "gssi" #_nsym, \
804*7f2fe78bSCy Schubert (void (**)())&(_mech)->_psym \
805*7f2fe78bSCy Schubert ## _nsym, \
806*7f2fe78bSCy Schubert &errinfo) || errinfo.code) { \
807*7f2fe78bSCy Schubert (_mech)->_psym ## _nsym = NULL; \
808*7f2fe78bSCy Schubert k5_clear_error(&errinfo); \
809*7f2fe78bSCy Schubert } \
810*7f2fe78bSCy Schubert } while (0)
811*7f2fe78bSCy Schubert
812*7f2fe78bSCy Schubert /* Build an interposer mechanism function table from dl. */
813*7f2fe78bSCy Schubert static gss_mechanism
build_interMech(void * dl,const gss_OID mech_type)814*7f2fe78bSCy Schubert build_interMech(void *dl, const gss_OID mech_type)
815*7f2fe78bSCy Schubert {
816*7f2fe78bSCy Schubert gss_mechanism mech;
817*7f2fe78bSCy Schubert
818*7f2fe78bSCy Schubert mech = calloc(1, sizeof(*mech));
819*7f2fe78bSCy Schubert if (mech == NULL) {
820*7f2fe78bSCy Schubert return NULL;
821*7f2fe78bSCy Schubert }
822*7f2fe78bSCy Schubert
823*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _acquire_cred);
824*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _release_cred);
825*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _init_sec_context);
826*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _accept_sec_context);
827*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _process_context_token);
828*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _delete_sec_context);
829*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _context_time);
830*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _get_mic);
831*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _verify_mic);
832*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _wrap);
833*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _unwrap);
834*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _display_status);
835*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _indicate_mechs);
836*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _compare_name);
837*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _display_name);
838*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _import_name);
839*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _release_name);
840*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_cred);
841*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _add_cred);
842*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _export_sec_context);
843*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _import_sec_context);
844*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_cred_by_mech);
845*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_names_for_mech);
846*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_context);
847*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _internal_release_oid);
848*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _wrap_size_limit);
849*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _localname);
850*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _authorize_localname);
851*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _export_name);
852*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _duplicate_name);
853*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _store_cred);
854*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_sec_context_by_oid);
855*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_cred_by_oid);
856*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _set_sec_context_option);
857*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _set_cred_option);
858*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _mech_invoke);
859*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _wrap_aead);
860*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _unwrap_aead);
861*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _wrap_iov);
862*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _unwrap_iov);
863*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _wrap_iov_length);
864*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _complete_auth_token);
865*7f2fe78bSCy Schubert /* Services4User (introduced in 1.8) */
866*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _acquire_cred_impersonate_name);
867*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _add_cred_impersonate_name);
868*7f2fe78bSCy Schubert /* Naming extensions (introduced in 1.8) */
869*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _display_name_ext);
870*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_name);
871*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _get_name_attribute);
872*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _set_name_attribute);
873*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _delete_name_attribute);
874*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _export_name_composite);
875*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _map_name_to_any);
876*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _release_any_name_mapping);
877*7f2fe78bSCy Schubert /* RFC 4401 (introduced in 1.8) */
878*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _pseudo_random);
879*7f2fe78bSCy Schubert /* RFC 4178 (introduced in 1.8; get_neg_mechs not implemented) */
880*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _set_neg_mechs);
881*7f2fe78bSCy Schubert /* draft-ietf-sasl-gs2 */
882*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_saslname_for_mech);
883*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_mech_for_saslname);
884*7f2fe78bSCy Schubert /* RFC 5587 */
885*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_attrs_for_mech);
886*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _acquire_cred_from);
887*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _store_cred_into);
888*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _acquire_cred_with_password);
889*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _export_cred);
890*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _import_cred);
891*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _import_sec_context_by_mech);
892*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _import_name_by_mech);
893*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _import_cred_by_mech);
894*7f2fe78bSCy Schubert /* gss_get_mic_iov extensions (added 1.12, implementable 1.20) */
895*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _get_mic_iov);
896*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _verify_mic_iov);
897*7f2fe78bSCy Schubert RESOLVE_GSSI_SYMBOL(dl, mech, gss, _get_mic_iov_length);
898*7f2fe78bSCy Schubert
899*7f2fe78bSCy Schubert mech->mech_type = *mech_type;
900*7f2fe78bSCy Schubert return mech;
901*7f2fe78bSCy Schubert }
902*7f2fe78bSCy Schubert
903*7f2fe78bSCy Schubert /*
904*7f2fe78bSCy Schubert * Concatenate an interposer mech OID and a real mech OID to create an
905*7f2fe78bSCy Schubert * identifier for the interposed mech. (The concatenation will not be a valid
906*7f2fe78bSCy Schubert * DER OID encoding, but the OID is only used internally.)
907*7f2fe78bSCy Schubert */
908*7f2fe78bSCy Schubert static gss_OID
interposed_oid(gss_OID pre,gss_OID real)909*7f2fe78bSCy Schubert interposed_oid(gss_OID pre, gss_OID real)
910*7f2fe78bSCy Schubert {
911*7f2fe78bSCy Schubert gss_OID o;
912*7f2fe78bSCy Schubert
913*7f2fe78bSCy Schubert o = (gss_OID)malloc(sizeof(gss_OID_desc));
914*7f2fe78bSCy Schubert if (!o)
915*7f2fe78bSCy Schubert return NULL;
916*7f2fe78bSCy Schubert
917*7f2fe78bSCy Schubert o->length = pre->length + real->length;
918*7f2fe78bSCy Schubert o->elements = malloc(o->length);
919*7f2fe78bSCy Schubert if (!o->elements) {
920*7f2fe78bSCy Schubert free(o);
921*7f2fe78bSCy Schubert return NULL;
922*7f2fe78bSCy Schubert }
923*7f2fe78bSCy Schubert
924*7f2fe78bSCy Schubert memcpy(o->elements, pre->elements, pre->length);
925*7f2fe78bSCy Schubert memcpy((char *)o->elements + pre->length, real->elements,
926*7f2fe78bSCy Schubert real->length);
927*7f2fe78bSCy Schubert
928*7f2fe78bSCy Schubert return o;
929*7f2fe78bSCy Schubert }
930*7f2fe78bSCy Schubert
931*7f2fe78bSCy Schubert static void
loadInterMech(gss_mech_info minfo)932*7f2fe78bSCy Schubert loadInterMech(gss_mech_info minfo)
933*7f2fe78bSCy Schubert {
934*7f2fe78bSCy Schubert struct plugin_file_handle *dl = NULL;
935*7f2fe78bSCy Schubert struct errinfo errinfo;
936*7f2fe78bSCy Schubert gss_OID_set (*isym)(const gss_OID);
937*7f2fe78bSCy Schubert gss_OID_set list;
938*7f2fe78bSCy Schubert gss_OID oid;
939*7f2fe78bSCy Schubert OM_uint32 min;
940*7f2fe78bSCy Schubert gss_mech_info mi;
941*7f2fe78bSCy Schubert size_t i;
942*7f2fe78bSCy Schubert
943*7f2fe78bSCy Schubert memset(&errinfo, 0, sizeof(errinfo));
944*7f2fe78bSCy Schubert
945*7f2fe78bSCy Schubert if (krb5int_open_plugin(minfo->uLibName, &dl, &errinfo) != 0 ||
946*7f2fe78bSCy Schubert errinfo.code != 0) {
947*7f2fe78bSCy Schubert return;
948*7f2fe78bSCy Schubert }
949*7f2fe78bSCy Schubert
950*7f2fe78bSCy Schubert if (krb5int_get_plugin_func(dl, MECH_INTERPOSER_SYM,
951*7f2fe78bSCy Schubert (void (**)())&isym, &errinfo) != 0)
952*7f2fe78bSCy Schubert goto cleanup;
953*7f2fe78bSCy Schubert
954*7f2fe78bSCy Schubert /* Get a list of mechs to interpose. */
955*7f2fe78bSCy Schubert list = (*isym)(minfo->mech_type);
956*7f2fe78bSCy Schubert if (!list)
957*7f2fe78bSCy Schubert goto cleanup;
958*7f2fe78bSCy Schubert minfo->mech = build_interMech(dl, minfo->mech_type);
959*7f2fe78bSCy Schubert if (minfo->mech == NULL)
960*7f2fe78bSCy Schubert goto cleanup;
961*7f2fe78bSCy Schubert minfo->freeMech = 1;
962*7f2fe78bSCy Schubert
963*7f2fe78bSCy Schubert /* Add interposer fields for each interposed mech. */
964*7f2fe78bSCy Schubert for (i = 0; i < list->count; i++) {
965*7f2fe78bSCy Schubert /* Skip this mech if it doesn't exist or is already
966*7f2fe78bSCy Schubert * interposed. */
967*7f2fe78bSCy Schubert oid = &list->elements[i];
968*7f2fe78bSCy Schubert mi = searchMechList(oid);
969*7f2fe78bSCy Schubert if (mi == NULL || mi->int_mech_type != NULL)
970*7f2fe78bSCy Schubert continue;
971*7f2fe78bSCy Schubert
972*7f2fe78bSCy Schubert /* Construct a special OID to represent the interposed mech. */
973*7f2fe78bSCy Schubert mi->int_mech_type = interposed_oid(minfo->mech_type, oid);
974*7f2fe78bSCy Schubert if (mi->int_mech_type == NULL)
975*7f2fe78bSCy Schubert continue;
976*7f2fe78bSCy Schubert
977*7f2fe78bSCy Schubert /* Save an alias to the interposer's function table. */
978*7f2fe78bSCy Schubert mi->int_mech = minfo->mech;
979*7f2fe78bSCy Schubert }
980*7f2fe78bSCy Schubert (void)gss_release_oid_set(&min, &list);
981*7f2fe78bSCy Schubert
982*7f2fe78bSCy Schubert minfo->dl_handle = dl;
983*7f2fe78bSCy Schubert dl = NULL;
984*7f2fe78bSCy Schubert
985*7f2fe78bSCy Schubert cleanup:
986*7f2fe78bSCy Schubert if (dl != NULL)
987*7f2fe78bSCy Schubert krb5int_close_plugin(dl);
988*7f2fe78bSCy Schubert k5_clear_error(&errinfo);
989*7f2fe78bSCy Schubert }
990*7f2fe78bSCy Schubert
991*7f2fe78bSCy Schubert static void
freeMechList(void)992*7f2fe78bSCy Schubert freeMechList(void)
993*7f2fe78bSCy Schubert {
994*7f2fe78bSCy Schubert gss_mech_info cf, next_cf;
995*7f2fe78bSCy Schubert
996*7f2fe78bSCy Schubert for (cf = g_mechList; cf != NULL; cf = next_cf) {
997*7f2fe78bSCy Schubert next_cf = cf->next;
998*7f2fe78bSCy Schubert releaseMechInfo(&cf);
999*7f2fe78bSCy Schubert }
1000*7f2fe78bSCy Schubert }
1001*7f2fe78bSCy Schubert
1002*7f2fe78bSCy Schubert /*
1003*7f2fe78bSCy Schubert * Determine the mechanism to use for a caller-specified mech OID. For the
1004*7f2fe78bSCy Schubert * real mech OID of an interposed mech, return the interposed OID. For an
1005*7f2fe78bSCy Schubert * interposed mech OID (which an interposer mech uses when re-entering the
1006*7f2fe78bSCy Schubert * mechglue), return the real mech OID. The returned OID is an alias and
1007*7f2fe78bSCy Schubert * should not be modified or freed.
1008*7f2fe78bSCy Schubert */
1009*7f2fe78bSCy Schubert OM_uint32
gssint_select_mech_type(OM_uint32 * minor,gss_const_OID oid,gss_OID * selected_oid)1010*7f2fe78bSCy Schubert gssint_select_mech_type(OM_uint32 *minor, gss_const_OID oid,
1011*7f2fe78bSCy Schubert gss_OID *selected_oid)
1012*7f2fe78bSCy Schubert {
1013*7f2fe78bSCy Schubert gss_mech_info minfo;
1014*7f2fe78bSCy Schubert OM_uint32 status;
1015*7f2fe78bSCy Schubert
1016*7f2fe78bSCy Schubert *selected_oid = GSS_C_NO_OID;
1017*7f2fe78bSCy Schubert
1018*7f2fe78bSCy Schubert if (gssint_mechglue_initialize_library() != 0)
1019*7f2fe78bSCy Schubert return GSS_S_FAILURE;
1020*7f2fe78bSCy Schubert
1021*7f2fe78bSCy Schubert k5_mutex_lock(&g_mechListLock);
1022*7f2fe78bSCy Schubert
1023*7f2fe78bSCy Schubert /* Read conf file at least once so that interposer plugins have a
1024*7f2fe78bSCy Schubert * chance of getting initialized. */
1025*7f2fe78bSCy Schubert initMechList();
1026*7f2fe78bSCy Schubert
1027*7f2fe78bSCy Schubert minfo = g_mechList;
1028*7f2fe78bSCy Schubert if (oid == GSS_C_NULL_OID)
1029*7f2fe78bSCy Schubert oid = minfo->mech_type;
1030*7f2fe78bSCy Schubert while (minfo != NULL) {
1031*7f2fe78bSCy Schubert if (g_OID_equal(minfo->mech_type, oid)) {
1032*7f2fe78bSCy Schubert if (minfo->int_mech_type != GSS_C_NO_OID)
1033*7f2fe78bSCy Schubert *selected_oid = minfo->int_mech_type;
1034*7f2fe78bSCy Schubert else
1035*7f2fe78bSCy Schubert *selected_oid = minfo->mech_type;
1036*7f2fe78bSCy Schubert status = GSS_S_COMPLETE;
1037*7f2fe78bSCy Schubert goto done;
1038*7f2fe78bSCy Schubert } else if ((minfo->int_mech_type != GSS_C_NO_OID) &&
1039*7f2fe78bSCy Schubert (g_OID_equal(minfo->int_mech_type, oid))) {
1040*7f2fe78bSCy Schubert *selected_oid = minfo->mech_type;
1041*7f2fe78bSCy Schubert status = GSS_S_COMPLETE;
1042*7f2fe78bSCy Schubert goto done;
1043*7f2fe78bSCy Schubert }
1044*7f2fe78bSCy Schubert minfo = minfo->next;
1045*7f2fe78bSCy Schubert }
1046*7f2fe78bSCy Schubert status = GSS_S_BAD_MECH;
1047*7f2fe78bSCy Schubert
1048*7f2fe78bSCy Schubert done:
1049*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
1050*7f2fe78bSCy Schubert return status;
1051*7f2fe78bSCy Schubert }
1052*7f2fe78bSCy Schubert
1053*7f2fe78bSCy Schubert /* If oid is an interposed OID, return the corresponding real mech OID. If
1054*7f2fe78bSCy Schubert * it's a real mech OID, return it unmodified. Otherwised return null. */
1055*7f2fe78bSCy Schubert gss_OID
gssint_get_public_oid(gss_const_OID oid)1056*7f2fe78bSCy Schubert gssint_get_public_oid(gss_const_OID oid)
1057*7f2fe78bSCy Schubert {
1058*7f2fe78bSCy Schubert gss_mech_info minfo;
1059*7f2fe78bSCy Schubert gss_OID public_oid = GSS_C_NO_OID;
1060*7f2fe78bSCy Schubert
1061*7f2fe78bSCy Schubert /* if oid is null -> then get default which is the first in the list */
1062*7f2fe78bSCy Schubert if (oid == GSS_C_NO_OID)
1063*7f2fe78bSCy Schubert return GSS_C_NO_OID;
1064*7f2fe78bSCy Schubert
1065*7f2fe78bSCy Schubert if (gssint_mechglue_initialize_library() != 0)
1066*7f2fe78bSCy Schubert return GSS_C_NO_OID;
1067*7f2fe78bSCy Schubert
1068*7f2fe78bSCy Schubert k5_mutex_lock(&g_mechListLock);
1069*7f2fe78bSCy Schubert
1070*7f2fe78bSCy Schubert for (minfo = g_mechList; minfo != NULL; minfo = minfo->next) {
1071*7f2fe78bSCy Schubert if (minfo->is_interposer)
1072*7f2fe78bSCy Schubert continue;
1073*7f2fe78bSCy Schubert if (g_OID_equal(minfo->mech_type, oid) ||
1074*7f2fe78bSCy Schubert ((minfo->int_mech_type != GSS_C_NO_OID) &&
1075*7f2fe78bSCy Schubert (g_OID_equal(minfo->int_mech_type, oid)))) {
1076*7f2fe78bSCy Schubert public_oid = minfo->mech_type;
1077*7f2fe78bSCy Schubert break;
1078*7f2fe78bSCy Schubert }
1079*7f2fe78bSCy Schubert }
1080*7f2fe78bSCy Schubert
1081*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
1082*7f2fe78bSCy Schubert return public_oid;
1083*7f2fe78bSCy Schubert }
1084*7f2fe78bSCy Schubert
1085*7f2fe78bSCy Schubert /* Translate a vector of oids (as from a union cred struct) into a set of
1086*7f2fe78bSCy Schubert * public OIDs using gssint_get_public_oid. */
1087*7f2fe78bSCy Schubert OM_uint32
gssint_make_public_oid_set(OM_uint32 * minor_status,gss_OID oids,int count,gss_OID_set * public_set)1088*7f2fe78bSCy Schubert gssint_make_public_oid_set(OM_uint32 *minor_status, gss_OID oids, int count,
1089*7f2fe78bSCy Schubert gss_OID_set *public_set)
1090*7f2fe78bSCy Schubert {
1091*7f2fe78bSCy Schubert OM_uint32 status, tmpmin;
1092*7f2fe78bSCy Schubert gss_OID_set set;
1093*7f2fe78bSCy Schubert gss_OID public_oid;
1094*7f2fe78bSCy Schubert int i;
1095*7f2fe78bSCy Schubert
1096*7f2fe78bSCy Schubert *public_set = GSS_C_NO_OID_SET;
1097*7f2fe78bSCy Schubert
1098*7f2fe78bSCy Schubert status = generic_gss_create_empty_oid_set(minor_status, &set);
1099*7f2fe78bSCy Schubert if (GSS_ERROR(status))
1100*7f2fe78bSCy Schubert return status;
1101*7f2fe78bSCy Schubert
1102*7f2fe78bSCy Schubert for (i = 0; i < count; i++) {
1103*7f2fe78bSCy Schubert public_oid = gssint_get_public_oid(&oids[i]);
1104*7f2fe78bSCy Schubert if (public_oid == GSS_C_NO_OID)
1105*7f2fe78bSCy Schubert continue;
1106*7f2fe78bSCy Schubert status = generic_gss_add_oid_set_member(minor_status,
1107*7f2fe78bSCy Schubert public_oid, &set);
1108*7f2fe78bSCy Schubert if (GSS_ERROR(status)) {
1109*7f2fe78bSCy Schubert (void) generic_gss_release_oid_set(&tmpmin, &set);
1110*7f2fe78bSCy Schubert return status;
1111*7f2fe78bSCy Schubert }
1112*7f2fe78bSCy Schubert }
1113*7f2fe78bSCy Schubert
1114*7f2fe78bSCy Schubert *public_set = set;
1115*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
1116*7f2fe78bSCy Schubert }
1117*7f2fe78bSCy Schubert
1118*7f2fe78bSCy Schubert /*
1119*7f2fe78bSCy Schubert * Register a mechanism. Called with g_mechListLock held.
1120*7f2fe78bSCy Schubert */
1121*7f2fe78bSCy Schubert
1122*7f2fe78bSCy Schubert /*
1123*7f2fe78bSCy Schubert * given the mechanism type, return the mechanism structure
1124*7f2fe78bSCy Schubert * containing the mechanism library entry points.
1125*7f2fe78bSCy Schubert * will return NULL if mech type is not found
1126*7f2fe78bSCy Schubert * This function will also trigger the loading of the mechanism
1127*7f2fe78bSCy Schubert * module if it has not been already loaded.
1128*7f2fe78bSCy Schubert */
1129*7f2fe78bSCy Schubert gss_mechanism
gssint_get_mechanism(gss_const_OID oid)1130*7f2fe78bSCy Schubert gssint_get_mechanism(gss_const_OID oid)
1131*7f2fe78bSCy Schubert {
1132*7f2fe78bSCy Schubert gss_mech_info aMech;
1133*7f2fe78bSCy Schubert gss_mechanism (*sym)(const gss_OID);
1134*7f2fe78bSCy Schubert struct plugin_file_handle *dl;
1135*7f2fe78bSCy Schubert struct errinfo errinfo;
1136*7f2fe78bSCy Schubert
1137*7f2fe78bSCy Schubert if (gssint_mechglue_initialize_library() != 0)
1138*7f2fe78bSCy Schubert return (NULL);
1139*7f2fe78bSCy Schubert
1140*7f2fe78bSCy Schubert k5_mutex_lock(&g_mechListLock);
1141*7f2fe78bSCy Schubert
1142*7f2fe78bSCy Schubert /* Check if the mechanism is already loaded. */
1143*7f2fe78bSCy Schubert aMech = g_mechList;
1144*7f2fe78bSCy Schubert if (oid == GSS_C_NULL_OID)
1145*7f2fe78bSCy Schubert oid = aMech->mech_type;
1146*7f2fe78bSCy Schubert while (aMech != NULL) {
1147*7f2fe78bSCy Schubert if (g_OID_equal(aMech->mech_type, oid) && aMech->mech) {
1148*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
1149*7f2fe78bSCy Schubert return aMech->mech;
1150*7f2fe78bSCy Schubert } else if (aMech->int_mech_type != GSS_C_NO_OID &&
1151*7f2fe78bSCy Schubert g_OID_equal(aMech->int_mech_type, oid)) {
1152*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
1153*7f2fe78bSCy Schubert return aMech->int_mech;
1154*7f2fe78bSCy Schubert }
1155*7f2fe78bSCy Schubert aMech = aMech->next;
1156*7f2fe78bSCy Schubert }
1157*7f2fe78bSCy Schubert
1158*7f2fe78bSCy Schubert /*
1159*7f2fe78bSCy Schubert * might need to re-read the configuration file before loading
1160*7f2fe78bSCy Schubert * the mechanism to ensure we have the latest info.
1161*7f2fe78bSCy Schubert */
1162*7f2fe78bSCy Schubert updateMechList();
1163*7f2fe78bSCy Schubert
1164*7f2fe78bSCy Schubert aMech = searchMechList(oid);
1165*7f2fe78bSCy Schubert
1166*7f2fe78bSCy Schubert /* is the mechanism present in the list ? */
1167*7f2fe78bSCy Schubert if (aMech == NULL) {
1168*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
1169*7f2fe78bSCy Schubert return ((gss_mechanism)NULL);
1170*7f2fe78bSCy Schubert }
1171*7f2fe78bSCy Schubert
1172*7f2fe78bSCy Schubert /* has another thread loaded the mech */
1173*7f2fe78bSCy Schubert if (aMech->mech) {
1174*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
1175*7f2fe78bSCy Schubert return (aMech->mech);
1176*7f2fe78bSCy Schubert }
1177*7f2fe78bSCy Schubert
1178*7f2fe78bSCy Schubert memset(&errinfo, 0, sizeof(errinfo));
1179*7f2fe78bSCy Schubert
1180*7f2fe78bSCy Schubert if (krb5int_open_plugin(aMech->uLibName, &dl, &errinfo) != 0 ||
1181*7f2fe78bSCy Schubert errinfo.code != 0) {
1182*7f2fe78bSCy Schubert k5_clear_error(&errinfo);
1183*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
1184*7f2fe78bSCy Schubert return ((gss_mechanism)NULL);
1185*7f2fe78bSCy Schubert }
1186*7f2fe78bSCy Schubert
1187*7f2fe78bSCy Schubert if (krb5int_get_plugin_func(dl, MECH_SYM, (void (**)())&sym,
1188*7f2fe78bSCy Schubert &errinfo) == 0) {
1189*7f2fe78bSCy Schubert /* Call the symbol to get the mechanism table */
1190*7f2fe78bSCy Schubert aMech->mech = (*sym)(aMech->mech_type);
1191*7f2fe78bSCy Schubert } else {
1192*7f2fe78bSCy Schubert /* Try dynamic dispatch table */
1193*7f2fe78bSCy Schubert k5_clear_error(&errinfo);
1194*7f2fe78bSCy Schubert aMech->mech = build_dynamicMech(dl, aMech->mech_type);
1195*7f2fe78bSCy Schubert aMech->freeMech = 1;
1196*7f2fe78bSCy Schubert }
1197*7f2fe78bSCy Schubert if (aMech->mech == NULL) {
1198*7f2fe78bSCy Schubert (void) krb5int_close_plugin(dl);
1199*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
1200*7f2fe78bSCy Schubert return ((gss_mechanism)NULL);
1201*7f2fe78bSCy Schubert }
1202*7f2fe78bSCy Schubert
1203*7f2fe78bSCy Schubert aMech->dl_handle = dl;
1204*7f2fe78bSCy Schubert
1205*7f2fe78bSCy Schubert k5_mutex_unlock(&g_mechListLock);
1206*7f2fe78bSCy Schubert return (aMech->mech);
1207*7f2fe78bSCy Schubert } /* gssint_get_mechanism */
1208*7f2fe78bSCy Schubert
1209*7f2fe78bSCy Schubert /*
1210*7f2fe78bSCy Schubert * this routine is used for searching the list of mechanism data.
1211*7f2fe78bSCy Schubert *
1212*7f2fe78bSCy Schubert * this needs to be called with g_mechListLock held.
1213*7f2fe78bSCy Schubert */
searchMechList(gss_const_OID oid)1214*7f2fe78bSCy Schubert static gss_mech_info searchMechList(gss_const_OID oid)
1215*7f2fe78bSCy Schubert {
1216*7f2fe78bSCy Schubert gss_mech_info aMech = g_mechList;
1217*7f2fe78bSCy Schubert
1218*7f2fe78bSCy Schubert /* if oid is null -> then get default which is the first in the list */
1219*7f2fe78bSCy Schubert if (oid == GSS_C_NULL_OID)
1220*7f2fe78bSCy Schubert return (aMech);
1221*7f2fe78bSCy Schubert
1222*7f2fe78bSCy Schubert while (aMech != NULL) {
1223*7f2fe78bSCy Schubert if (g_OID_equal(aMech->mech_type, oid))
1224*7f2fe78bSCy Schubert return (aMech);
1225*7f2fe78bSCy Schubert aMech = aMech->next;
1226*7f2fe78bSCy Schubert }
1227*7f2fe78bSCy Schubert
1228*7f2fe78bSCy Schubert /* none found */
1229*7f2fe78bSCy Schubert return ((gss_mech_info) NULL);
1230*7f2fe78bSCy Schubert } /* searchMechList */
1231*7f2fe78bSCy Schubert
1232*7f2fe78bSCy Schubert /* Return the first non-whitespace character starting from str. */
1233*7f2fe78bSCy Schubert static char *
skip_whitespace(char * str)1234*7f2fe78bSCy Schubert skip_whitespace(char *str)
1235*7f2fe78bSCy Schubert {
1236*7f2fe78bSCy Schubert while (isspace(*str))
1237*7f2fe78bSCy Schubert str++;
1238*7f2fe78bSCy Schubert return str;
1239*7f2fe78bSCy Schubert }
1240*7f2fe78bSCy Schubert
1241*7f2fe78bSCy Schubert /* Truncate str at the first whitespace character and return the first
1242*7f2fe78bSCy Schubert * non-whitespace character after that point. */
1243*7f2fe78bSCy Schubert static char *
delimit_ws(char * str)1244*7f2fe78bSCy Schubert delimit_ws(char *str)
1245*7f2fe78bSCy Schubert {
1246*7f2fe78bSCy Schubert while (*str != '\0' && !isspace(*str))
1247*7f2fe78bSCy Schubert str++;
1248*7f2fe78bSCy Schubert if (*str != '\0')
1249*7f2fe78bSCy Schubert *str++ = '\0';
1250*7f2fe78bSCy Schubert return skip_whitespace(str);
1251*7f2fe78bSCy Schubert }
1252*7f2fe78bSCy Schubert
1253*7f2fe78bSCy Schubert /* Truncate str at the first occurrence of delimiter and return the first
1254*7f2fe78bSCy Schubert * non-whitespace character after that point. */
1255*7f2fe78bSCy Schubert static char *
delimit(char * str,char delimiter)1256*7f2fe78bSCy Schubert delimit(char *str, char delimiter)
1257*7f2fe78bSCy Schubert {
1258*7f2fe78bSCy Schubert while (*str != '\0' && *str != delimiter)
1259*7f2fe78bSCy Schubert str++;
1260*7f2fe78bSCy Schubert if (*str != '\0')
1261*7f2fe78bSCy Schubert *str++ = '\0';
1262*7f2fe78bSCy Schubert return skip_whitespace(str);
1263*7f2fe78bSCy Schubert }
1264*7f2fe78bSCy Schubert
1265*7f2fe78bSCy Schubert /*
1266*7f2fe78bSCy Schubert * loads the configuration file
1267*7f2fe78bSCy Schubert * this is called while having a mutex lock on the mechanism list
1268*7f2fe78bSCy Schubert * entries for libraries that have been loaded can't be modified
1269*7f2fe78bSCy Schubert * mechNameStr and mech_type fields are not updated during updates
1270*7f2fe78bSCy Schubert */
1271*7f2fe78bSCy Schubert static void
loadConfigFile(const char * fileName)1272*7f2fe78bSCy Schubert loadConfigFile(const char *fileName)
1273*7f2fe78bSCy Schubert {
1274*7f2fe78bSCy Schubert char *sharedLib, *kernMod, *modOptions, *modType, *oid, *next;
1275*7f2fe78bSCy Schubert char buffer[BUFSIZ], *oidStr;
1276*7f2fe78bSCy Schubert FILE *confFile;
1277*7f2fe78bSCy Schubert
1278*7f2fe78bSCy Schubert if ((confFile = fopen(fileName, "r")) == NULL) {
1279*7f2fe78bSCy Schubert return;
1280*7f2fe78bSCy Schubert }
1281*7f2fe78bSCy Schubert
1282*7f2fe78bSCy Schubert (void) memset(buffer, 0, sizeof (buffer));
1283*7f2fe78bSCy Schubert while (fgets(buffer, BUFSIZ, confFile) != NULL) {
1284*7f2fe78bSCy Schubert
1285*7f2fe78bSCy Schubert /* ignore lines beginning with # */
1286*7f2fe78bSCy Schubert if (*buffer == '#')
1287*7f2fe78bSCy Schubert continue;
1288*7f2fe78bSCy Schubert
1289*7f2fe78bSCy Schubert /* Parse out the name, oid, and shared library path. */
1290*7f2fe78bSCy Schubert oidStr = buffer;
1291*7f2fe78bSCy Schubert oid = delimit_ws(oidStr);
1292*7f2fe78bSCy Schubert if (*oid == '\0')
1293*7f2fe78bSCy Schubert continue;
1294*7f2fe78bSCy Schubert sharedLib = delimit_ws(oid);
1295*7f2fe78bSCy Schubert if (*sharedLib == '\0')
1296*7f2fe78bSCy Schubert continue;
1297*7f2fe78bSCy Schubert next = delimit_ws(sharedLib);
1298*7f2fe78bSCy Schubert
1299*7f2fe78bSCy Schubert /* Parse out the kernel module name if present. */
1300*7f2fe78bSCy Schubert if (*next != '\0' && *next != '[' && *next != '<') {
1301*7f2fe78bSCy Schubert kernMod = next;
1302*7f2fe78bSCy Schubert next = delimit_ws(kernMod);
1303*7f2fe78bSCy Schubert } else {
1304*7f2fe78bSCy Schubert kernMod = NULL;
1305*7f2fe78bSCy Schubert }
1306*7f2fe78bSCy Schubert
1307*7f2fe78bSCy Schubert /* Parse out the module options if present. */
1308*7f2fe78bSCy Schubert if (*next == '[') {
1309*7f2fe78bSCy Schubert modOptions = next + 1;
1310*7f2fe78bSCy Schubert next = delimit(modOptions, ']');
1311*7f2fe78bSCy Schubert } else {
1312*7f2fe78bSCy Schubert modOptions = NULL;
1313*7f2fe78bSCy Schubert }
1314*7f2fe78bSCy Schubert
1315*7f2fe78bSCy Schubert /* Parse out the module type if present. */
1316*7f2fe78bSCy Schubert if (*next == '<') {
1317*7f2fe78bSCy Schubert modType = next + 1;
1318*7f2fe78bSCy Schubert (void)delimit(modType, '>');
1319*7f2fe78bSCy Schubert } else {
1320*7f2fe78bSCy Schubert modType = NULL;
1321*7f2fe78bSCy Schubert }
1322*7f2fe78bSCy Schubert
1323*7f2fe78bSCy Schubert addConfigEntry(oidStr, oid, sharedLib, kernMod, modOptions,
1324*7f2fe78bSCy Schubert modType);
1325*7f2fe78bSCy Schubert } /* while */
1326*7f2fe78bSCy Schubert (void) fclose(confFile);
1327*7f2fe78bSCy Schubert } /* loadConfigFile */
1328*7f2fe78bSCy Schubert
1329*7f2fe78bSCy Schubert #if defined(_WIN32)
1330*7f2fe78bSCy Schubert
1331*7f2fe78bSCy Schubert static time_t
filetimeToTimet(const FILETIME * ft)1332*7f2fe78bSCy Schubert filetimeToTimet(const FILETIME *ft)
1333*7f2fe78bSCy Schubert {
1334*7f2fe78bSCy Schubert ULARGE_INTEGER ull;
1335*7f2fe78bSCy Schubert
1336*7f2fe78bSCy Schubert ull.LowPart = ft->dwLowDateTime;
1337*7f2fe78bSCy Schubert ull.HighPart = ft->dwHighDateTime;
1338*7f2fe78bSCy Schubert return (time_t)(ull.QuadPart / 10000000ULL - 11644473600ULL);
1339*7f2fe78bSCy Schubert }
1340*7f2fe78bSCy Schubert
1341*7f2fe78bSCy Schubert static time_t
getRegConfigModTime(const char * keyPath)1342*7f2fe78bSCy Schubert getRegConfigModTime(const char *keyPath)
1343*7f2fe78bSCy Schubert {
1344*7f2fe78bSCy Schubert time_t currentUserModTime = getRegKeyModTime(HKEY_CURRENT_USER,
1345*7f2fe78bSCy Schubert keyPath);
1346*7f2fe78bSCy Schubert time_t localMachineModTime = getRegKeyModTime(HKEY_LOCAL_MACHINE,
1347*7f2fe78bSCy Schubert keyPath);
1348*7f2fe78bSCy Schubert
1349*7f2fe78bSCy Schubert return currentUserModTime > localMachineModTime ? currentUserModTime :
1350*7f2fe78bSCy Schubert localMachineModTime;
1351*7f2fe78bSCy Schubert }
1352*7f2fe78bSCy Schubert
1353*7f2fe78bSCy Schubert static time_t
getRegKeyModTime(HKEY hBaseKey,const char * keyPath)1354*7f2fe78bSCy Schubert getRegKeyModTime(HKEY hBaseKey, const char *keyPath)
1355*7f2fe78bSCy Schubert {
1356*7f2fe78bSCy Schubert HKEY hConfigKey;
1357*7f2fe78bSCy Schubert HRESULT rc;
1358*7f2fe78bSCy Schubert int iSubKey = 0;
1359*7f2fe78bSCy Schubert time_t modTime = 0, keyModTime;
1360*7f2fe78bSCy Schubert FILETIME keyLastWriteTime;
1361*7f2fe78bSCy Schubert char subKeyName[256];
1362*7f2fe78bSCy Schubert
1363*7f2fe78bSCy Schubert if ((rc = RegOpenKeyEx(hBaseKey, keyPath, 0, KEY_ENUMERATE_SUB_KEYS,
1364*7f2fe78bSCy Schubert &hConfigKey)) != ERROR_SUCCESS) {
1365*7f2fe78bSCy Schubert /* TODO: log error message */
1366*7f2fe78bSCy Schubert return 0;
1367*7f2fe78bSCy Schubert }
1368*7f2fe78bSCy Schubert do {
1369*7f2fe78bSCy Schubert int subKeyNameSize=sizeof(subKeyName)/sizeof(subKeyName[0]);
1370*7f2fe78bSCy Schubert if ((rc = RegEnumKeyEx(hConfigKey, iSubKey++, subKeyName,
1371*7f2fe78bSCy Schubert &subKeyNameSize, NULL, NULL, NULL,
1372*7f2fe78bSCy Schubert &keyLastWriteTime)) != ERROR_SUCCESS) {
1373*7f2fe78bSCy Schubert break;
1374*7f2fe78bSCy Schubert }
1375*7f2fe78bSCy Schubert keyModTime = filetimeToTimet(&keyLastWriteTime);
1376*7f2fe78bSCy Schubert if (modTime < keyModTime) {
1377*7f2fe78bSCy Schubert modTime = keyModTime;
1378*7f2fe78bSCy Schubert }
1379*7f2fe78bSCy Schubert } while (1);
1380*7f2fe78bSCy Schubert RegCloseKey(hConfigKey);
1381*7f2fe78bSCy Schubert return modTime;
1382*7f2fe78bSCy Schubert }
1383*7f2fe78bSCy Schubert
1384*7f2fe78bSCy Schubert static void
getRegKeyValue(HKEY hKey,const char * keyPath,const char * valueName,void ** data,DWORD * dataLen)1385*7f2fe78bSCy Schubert getRegKeyValue(HKEY hKey, const char *keyPath, const char *valueName,
1386*7f2fe78bSCy Schubert void **data, DWORD* dataLen)
1387*7f2fe78bSCy Schubert {
1388*7f2fe78bSCy Schubert DWORD sizeRequired=*dataLen;
1389*7f2fe78bSCy Schubert HRESULT hr;
1390*7f2fe78bSCy Schubert /* Get data length required */
1391*7f2fe78bSCy Schubert if ((hr = RegGetValue(hKey, keyPath, valueName, RRF_RT_REG_SZ, NULL,
1392*7f2fe78bSCy Schubert NULL, &sizeRequired)) != ERROR_SUCCESS) {
1393*7f2fe78bSCy Schubert /* TODO: LOG registry error */
1394*7f2fe78bSCy Schubert return;
1395*7f2fe78bSCy Schubert }
1396*7f2fe78bSCy Schubert /* adjust data buffer size if necessary */
1397*7f2fe78bSCy Schubert if (*dataLen < sizeRequired) {
1398*7f2fe78bSCy Schubert *dataLen = sizeRequired;
1399*7f2fe78bSCy Schubert *data = realloc(*data, sizeRequired);
1400*7f2fe78bSCy Schubert if (!*data) {
1401*7f2fe78bSCy Schubert *dataLen = 0;
1402*7f2fe78bSCy Schubert /* TODO: LOG OOM ERROR! */
1403*7f2fe78bSCy Schubert return;
1404*7f2fe78bSCy Schubert }
1405*7f2fe78bSCy Schubert }
1406*7f2fe78bSCy Schubert /* get data */
1407*7f2fe78bSCy Schubert if ((hr = RegGetValue(hKey, keyPath, valueName, RRF_RT_REG_SZ, NULL,
1408*7f2fe78bSCy Schubert *data, &sizeRequired)) != ERROR_SUCCESS) {
1409*7f2fe78bSCy Schubert /* LOG registry error */
1410*7f2fe78bSCy Schubert return;
1411*7f2fe78bSCy Schubert }
1412*7f2fe78bSCy Schubert }
1413*7f2fe78bSCy Schubert
1414*7f2fe78bSCy Schubert static void
loadConfigFromRegistry(HKEY hBaseKey,const char * keyPath)1415*7f2fe78bSCy Schubert loadConfigFromRegistry(HKEY hBaseKey, const char *keyPath)
1416*7f2fe78bSCy Schubert {
1417*7f2fe78bSCy Schubert HKEY hConfigKey;
1418*7f2fe78bSCy Schubert DWORD iSubKey, nSubKeys, maxSubKeyNameLen, modTypeLen;
1419*7f2fe78bSCy Schubert char *oidStr = NULL, *oid = NULL, *sharedLib = NULL, *kernMod = NULL;
1420*7f2fe78bSCy Schubert char *modOptions = NULL, *modType = NULL;
1421*7f2fe78bSCy Schubert DWORD oidStrLen = 0, oidLen = 0, sharedLibLen = 0, kernModLen = 0;
1422*7f2fe78bSCy Schubert DWORD modOptionsLen = 0;
1423*7f2fe78bSCy Schubert HRESULT rc;
1424*7f2fe78bSCy Schubert
1425*7f2fe78bSCy Schubert if ((rc = RegOpenKeyEx(hBaseKey, keyPath, 0,
1426*7f2fe78bSCy Schubert KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,
1427*7f2fe78bSCy Schubert &hConfigKey)) != ERROR_SUCCESS) {
1428*7f2fe78bSCy Schubert /* TODO: log registry error */
1429*7f2fe78bSCy Schubert return;
1430*7f2fe78bSCy Schubert }
1431*7f2fe78bSCy Schubert
1432*7f2fe78bSCy Schubert if ((rc = RegQueryInfoKey(hConfigKey,
1433*7f2fe78bSCy Schubert NULL, /* lpClass */
1434*7f2fe78bSCy Schubert NULL, /* lpcClass */
1435*7f2fe78bSCy Schubert NULL, /* lpReserved */
1436*7f2fe78bSCy Schubert &nSubKeys,
1437*7f2fe78bSCy Schubert &maxSubKeyNameLen,
1438*7f2fe78bSCy Schubert NULL, /* lpcMaxClassLen */
1439*7f2fe78bSCy Schubert NULL, /* lpcValues */
1440*7f2fe78bSCy Schubert NULL, /* lpcMaxValueNameLen */
1441*7f2fe78bSCy Schubert NULL, /* lpcMaxValueLen */
1442*7f2fe78bSCy Schubert NULL, /* lpcbSecurityDescriptor */
1443*7f2fe78bSCy Schubert NULL /* lpftLastWriteTime */ )) != ERROR_SUCCESS) {
1444*7f2fe78bSCy Schubert goto cleanup;
1445*7f2fe78bSCy Schubert }
1446*7f2fe78bSCy Schubert oidStr = malloc(++maxSubKeyNameLen);
1447*7f2fe78bSCy Schubert if (!oidStr) {
1448*7f2fe78bSCy Schubert goto cleanup;
1449*7f2fe78bSCy Schubert }
1450*7f2fe78bSCy Schubert for (iSubKey=0; iSubKey<nSubKeys; iSubKey++) {
1451*7f2fe78bSCy Schubert oidStrLen = maxSubKeyNameLen;
1452*7f2fe78bSCy Schubert if ((rc = RegEnumKeyEx(hConfigKey, iSubKey, oidStr, &oidStrLen,
1453*7f2fe78bSCy Schubert NULL, NULL, NULL, NULL)) !=
1454*7f2fe78bSCy Schubert ERROR_SUCCESS) {
1455*7f2fe78bSCy Schubert /* TODO: log registry error */
1456*7f2fe78bSCy Schubert continue;
1457*7f2fe78bSCy Schubert }
1458*7f2fe78bSCy Schubert getRegKeyValue(hConfigKey, oidStr, "OID", &oid, &oidLen);
1459*7f2fe78bSCy Schubert getRegKeyValue(hConfigKey, oidStr, "Shared Library",
1460*7f2fe78bSCy Schubert &sharedLib, &sharedLibLen);
1461*7f2fe78bSCy Schubert getRegKeyValue(hConfigKey, oidStr, "Kernel Module", &kernMod,
1462*7f2fe78bSCy Schubert &kernModLen);
1463*7f2fe78bSCy Schubert getRegKeyValue(hConfigKey, oidStr, "Options", &modOptions,
1464*7f2fe78bSCy Schubert &modOptionsLen);
1465*7f2fe78bSCy Schubert getRegKeyValue(hConfigKey, oidStr, "Type", &modType,
1466*7f2fe78bSCy Schubert &modTypeLen);
1467*7f2fe78bSCy Schubert addConfigEntry(oidStr, oid, sharedLib, kernMod, modOptions,
1468*7f2fe78bSCy Schubert modType);
1469*7f2fe78bSCy Schubert }
1470*7f2fe78bSCy Schubert cleanup:
1471*7f2fe78bSCy Schubert RegCloseKey(hConfigKey);
1472*7f2fe78bSCy Schubert if (oidStr) {
1473*7f2fe78bSCy Schubert free(oidStr);
1474*7f2fe78bSCy Schubert }
1475*7f2fe78bSCy Schubert if (oid) {
1476*7f2fe78bSCy Schubert free(oid);
1477*7f2fe78bSCy Schubert }
1478*7f2fe78bSCy Schubert if (sharedLib) {
1479*7f2fe78bSCy Schubert free(sharedLib);
1480*7f2fe78bSCy Schubert }
1481*7f2fe78bSCy Schubert if (kernMod) {
1482*7f2fe78bSCy Schubert free(kernMod);
1483*7f2fe78bSCy Schubert }
1484*7f2fe78bSCy Schubert if (modOptions) {
1485*7f2fe78bSCy Schubert free(modOptions);
1486*7f2fe78bSCy Schubert }
1487*7f2fe78bSCy Schubert }
1488*7f2fe78bSCy Schubert #endif
1489*7f2fe78bSCy Schubert
1490*7f2fe78bSCy Schubert static void
addConfigEntry(const char * oidStr,const char * oid,const char * sharedLib,const char * kernMod,const char * modOptions,const char * modType)1491*7f2fe78bSCy Schubert addConfigEntry(const char *oidStr, const char *oid, const char *sharedLib,
1492*7f2fe78bSCy Schubert const char *kernMod, const char *modOptions,
1493*7f2fe78bSCy Schubert const char *modType)
1494*7f2fe78bSCy Schubert {
1495*7f2fe78bSCy Schubert #if defined(_WIN32)
1496*7f2fe78bSCy Schubert const char *sharedPath;
1497*7f2fe78bSCy Schubert #else
1498*7f2fe78bSCy Schubert char sharedPath[sizeof (MECH_LIB_PREFIX) + BUFSIZ];
1499*7f2fe78bSCy Schubert #endif
1500*7f2fe78bSCy Schubert char *tmpStr;
1501*7f2fe78bSCy Schubert gss_OID mechOid;
1502*7f2fe78bSCy Schubert gss_mech_info aMech, tmp;
1503*7f2fe78bSCy Schubert OM_uint32 minor;
1504*7f2fe78bSCy Schubert gss_buffer_desc oidBuf;
1505*7f2fe78bSCy Schubert
1506*7f2fe78bSCy Schubert if ((!oid) || (!oidStr)) {
1507*7f2fe78bSCy Schubert return;
1508*7f2fe78bSCy Schubert }
1509*7f2fe78bSCy Schubert /*
1510*7f2fe78bSCy Schubert * check if an entry for this oid already exists
1511*7f2fe78bSCy Schubert * if it does, and the library is already loaded then
1512*7f2fe78bSCy Schubert * we can't modify it, so skip it
1513*7f2fe78bSCy Schubert */
1514*7f2fe78bSCy Schubert oidBuf.value = (void *)oid;
1515*7f2fe78bSCy Schubert oidBuf.length = strlen(oid);
1516*7f2fe78bSCy Schubert if (generic_gss_str_to_oid(&minor, &oidBuf, &mechOid)
1517*7f2fe78bSCy Schubert != GSS_S_COMPLETE) {
1518*7f2fe78bSCy Schubert return;
1519*7f2fe78bSCy Schubert }
1520*7f2fe78bSCy Schubert
1521*7f2fe78bSCy Schubert aMech = searchMechList(mechOid);
1522*7f2fe78bSCy Schubert if (aMech && aMech->mech) {
1523*7f2fe78bSCy Schubert generic_gss_release_oid(&minor, &mechOid);
1524*7f2fe78bSCy Schubert return;
1525*7f2fe78bSCy Schubert }
1526*7f2fe78bSCy Schubert
1527*7f2fe78bSCy Schubert /*
1528*7f2fe78bSCy Schubert * If that's all, then this is a corrupt entry. Skip it.
1529*7f2fe78bSCy Schubert */
1530*7f2fe78bSCy Schubert if (! *sharedLib) {
1531*7f2fe78bSCy Schubert generic_gss_release_oid(&minor, &mechOid);
1532*7f2fe78bSCy Schubert return;
1533*7f2fe78bSCy Schubert }
1534*7f2fe78bSCy Schubert #if defined(_WIN32)
1535*7f2fe78bSCy Schubert sharedPath = sharedLib;
1536*7f2fe78bSCy Schubert #else
1537*7f2fe78bSCy Schubert if (sharedLib[0] == '/')
1538*7f2fe78bSCy Schubert snprintf(sharedPath, sizeof(sharedPath), "%s", sharedLib);
1539*7f2fe78bSCy Schubert else
1540*7f2fe78bSCy Schubert snprintf(sharedPath, sizeof(sharedPath), "%s%s",
1541*7f2fe78bSCy Schubert MECH_LIB_PREFIX, sharedLib);
1542*7f2fe78bSCy Schubert #endif
1543*7f2fe78bSCy Schubert /*
1544*7f2fe78bSCy Schubert * are we creating a new mechanism entry or
1545*7f2fe78bSCy Schubert * just modifying existing (non loaded) mechanism entry
1546*7f2fe78bSCy Schubert */
1547*7f2fe78bSCy Schubert if (aMech) {
1548*7f2fe78bSCy Schubert /*
1549*7f2fe78bSCy Schubert * delete any old values and set new
1550*7f2fe78bSCy Schubert * mechNameStr and mech_type are not modified
1551*7f2fe78bSCy Schubert */
1552*7f2fe78bSCy Schubert if (aMech->kmodName) {
1553*7f2fe78bSCy Schubert free(aMech->kmodName);
1554*7f2fe78bSCy Schubert aMech->kmodName = NULL;
1555*7f2fe78bSCy Schubert }
1556*7f2fe78bSCy Schubert
1557*7f2fe78bSCy Schubert if (aMech->optionStr) {
1558*7f2fe78bSCy Schubert free(aMech->optionStr);
1559*7f2fe78bSCy Schubert aMech->optionStr = NULL;
1560*7f2fe78bSCy Schubert }
1561*7f2fe78bSCy Schubert
1562*7f2fe78bSCy Schubert if ((tmpStr = strdup(sharedPath)) != NULL) {
1563*7f2fe78bSCy Schubert if (aMech->uLibName)
1564*7f2fe78bSCy Schubert free(aMech->uLibName);
1565*7f2fe78bSCy Schubert aMech->uLibName = tmpStr;
1566*7f2fe78bSCy Schubert }
1567*7f2fe78bSCy Schubert
1568*7f2fe78bSCy Schubert if (kernMod) /* this is an optional parameter */
1569*7f2fe78bSCy Schubert aMech->kmodName = strdup(kernMod);
1570*7f2fe78bSCy Schubert
1571*7f2fe78bSCy Schubert if (modOptions) /* optional module options */
1572*7f2fe78bSCy Schubert aMech->optionStr = strdup(modOptions);
1573*7f2fe78bSCy Schubert
1574*7f2fe78bSCy Schubert /* the oid is already set */
1575*7f2fe78bSCy Schubert generic_gss_release_oid(&minor, &mechOid);
1576*7f2fe78bSCy Schubert return;
1577*7f2fe78bSCy Schubert }
1578*7f2fe78bSCy Schubert
1579*7f2fe78bSCy Schubert /* adding a new entry */
1580*7f2fe78bSCy Schubert aMech = calloc(1, sizeof (struct gss_mech_config));
1581*7f2fe78bSCy Schubert if (aMech == NULL) {
1582*7f2fe78bSCy Schubert generic_gss_release_oid(&minor, &mechOid);
1583*7f2fe78bSCy Schubert return;
1584*7f2fe78bSCy Schubert }
1585*7f2fe78bSCy Schubert aMech->mech_type = mechOid;
1586*7f2fe78bSCy Schubert aMech->uLibName = strdup(sharedPath);
1587*7f2fe78bSCy Schubert aMech->mechNameStr = strdup(oidStr);
1588*7f2fe78bSCy Schubert aMech->freeMech = 0;
1589*7f2fe78bSCy Schubert
1590*7f2fe78bSCy Schubert /* check if any memory allocations failed - bad news */
1591*7f2fe78bSCy Schubert if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) {
1592*7f2fe78bSCy Schubert if (aMech->uLibName)
1593*7f2fe78bSCy Schubert free(aMech->uLibName);
1594*7f2fe78bSCy Schubert if (aMech->mechNameStr)
1595*7f2fe78bSCy Schubert free(aMech->mechNameStr);
1596*7f2fe78bSCy Schubert generic_gss_release_oid(&minor, &mechOid);
1597*7f2fe78bSCy Schubert free(aMech);
1598*7f2fe78bSCy Schubert return;
1599*7f2fe78bSCy Schubert }
1600*7f2fe78bSCy Schubert if (kernMod) /* this is an optional parameter */
1601*7f2fe78bSCy Schubert aMech->kmodName = strdup(kernMod);
1602*7f2fe78bSCy Schubert
1603*7f2fe78bSCy Schubert if (modOptions)
1604*7f2fe78bSCy Schubert aMech->optionStr = strdup(modOptions);
1605*7f2fe78bSCy Schubert
1606*7f2fe78bSCy Schubert if (modType && strcmp(modType, "interposer") == 0)
1607*7f2fe78bSCy Schubert aMech->is_interposer = 1;
1608*7f2fe78bSCy Schubert
1609*7f2fe78bSCy Schubert /*
1610*7f2fe78bSCy Schubert * add the new entry to the end of the list - make sure
1611*7f2fe78bSCy Schubert * that only complete entries are added because other
1612*7f2fe78bSCy Schubert * threads might currently be searching the list.
1613*7f2fe78bSCy Schubert */
1614*7f2fe78bSCy Schubert tmp = g_mechListTail;
1615*7f2fe78bSCy Schubert g_mechListTail = aMech;
1616*7f2fe78bSCy Schubert
1617*7f2fe78bSCy Schubert if (tmp != NULL)
1618*7f2fe78bSCy Schubert tmp->next = aMech;
1619*7f2fe78bSCy Schubert
1620*7f2fe78bSCy Schubert if (g_mechList == NULL)
1621*7f2fe78bSCy Schubert g_mechList = aMech;
1622*7f2fe78bSCy Schubert }
1623*7f2fe78bSCy Schubert
1624