]> git.decadent.org.uk Git - nfs-utils.git/blob - support/gssapi/g_initialize.c
release 1.0.7-pre2
[nfs-utils.git] / support / gssapi / g_initialize.c
1 /* #ident  "@(#)g_initialize.c 1.2     96/02/06 SMI" */
2
3 /*
4  * Copyright 1996 by Sun Microsystems, Inc.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software
7  * and its documentation for any purpose is hereby granted without fee,
8  * provided that the above copyright notice appears in all copies and
9  * that both that copyright notice and this permission notice appear in
10  * supporting documentation, and that the name of Sun Microsystems not be used
11  * in advertising or publicity pertaining to distribution of the software
12  * without specific, written prior permission. Sun Microsystems makes no
13  * representations about the suitability of this software for any
14  * purpose.  It is provided "as is" without express or implied warranty.
15  *
16  * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22  * PERFORMANCE OF THIS SOFTWARE.
23  */
24
25 /*
26  * This function will initialize the gssapi mechglue library
27  */
28
29 #include "config.h"
30 #include "mglueP.h"
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif
34
35 #include <stdio.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <errno.h>
39
40 #ifdef USE_SOLARIS_SHARED_LIBRARIES
41 #include <dlfcn.h>
42
43 #define MECH_CONF "/etc/mech.conf"
44 #define MECH_SYM "gss_mech_initialize"
45
46 static void solaris_initialize (void);
47 #endif /* USE_SOLARIS_SHARED_LIBRARIES */
48
49 #ifdef __linux__
50 #define USE_LINUX_SHARED_LIBRARIES
51 #endif
52
53 #ifdef USE_LINUX_SHARED_LIBRARIES
54 #include <dlfcn.h>
55 #define MECH_CONF "/etc/gssapi_mech.conf"
56 #define MECH_SYM "gss_mech_initialize"
57 static void linux_initialize (void);
58 #endif /* USE_LINUX_SHARED_LIBRARIES */
59
60 #define g_OID_equal(o1,o2) \
61    (((o1)->length == (o2)->length) && \
62     (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
63
64 extern gss_mechanism krb5_gss_initialize();
65
66 static int _gss_initialized = 0;
67
68 static struct gss_config null_mech = {
69   {0,NULL}};
70
71 gss_mechanism *__gss_mechs_array = NULL;
72
73 /*
74  * This function will add a new mechanism to the mechs_array
75  */
76
77 static OM_uint32
78 add_mechanism (mech, replace)
79      gss_mechanism mech;
80      int replace;
81 {
82     gss_mechanism *     temp_array;
83     gss_OID_set         mech_names;
84     OM_uint32           minor_status, major_status;
85     unsigned int        i;
86
87     if (mech == NULL)
88         return GSS_S_COMPLETE;
89
90     /* initialize the mechs_array if it hasn't already been initialized */
91     if (__gss_mechs_array == NULL) {
92         __gss_mechs_array = (gss_mechanism *) malloc (sizeof(gss_mechanism));
93
94         if (__gss_mechs_array == NULL)
95             return ENOMEM;
96
97         __gss_mechs_array[0] = &null_mech;
98     }
99
100     /*
101      * Find the length of __gss_mechs_array, and look for an existing
102      * entry for this OID
103      */
104     for (i=0; __gss_mechs_array[i]->mech_type.length != 0; i++) {
105         if (!g_OID_equal(&__gss_mechs_array[i]->mech_type,
106                          &mech->mech_type))
107             continue;
108
109         /* We found a match.  Replace it? */
110         if (!replace)
111             return GSS_S_FAILURE;
112
113         __gss_mechs_array[i] = mech;
114         return GSS_S_COMPLETE;
115     }
116
117     /* we didn't find it -- add it to the end of the __gss_mechs_array */
118     temp_array = (gss_mechanism *) realloc(__gss_mechs_array,
119                                            (i+2)*sizeof(gss_mechanism));
120
121     if (temp_array == NULL)
122         return ENOMEM;
123
124     temp_array[i++] = mech;
125     temp_array[i] = &null_mech;
126
127     __gss_mechs_array = temp_array;
128
129     /*
130      * OK, now let's register all of the name types this mechanism
131      * knows how to deal with.
132      */
133     major_status = gss_inquire_names_for_mech(&minor_status, &mech->mech_type,
134                                               &mech_names);
135     if (major_status != GSS_S_COMPLETE)
136         return (GSS_S_COMPLETE);
137     for (i=0; i < mech_names->count; i++) {
138         gss_add_mech_name_type(&minor_status, &mech_names->elements[i],
139                                &mech->mech_type);
140     }
141     (void) gss_release_oid_set(&minor_status, &mech_names);
142
143     return GSS_S_COMPLETE;
144 }
145
146 void gss_initialize ()
147 {
148     /* Make sure we've not run already */
149     if (_gss_initialized)
150         return;
151     _gss_initialized = 1;
152
153 #ifdef USE_SOLARIS_SHARED_LIBRARIES
154     solaris_initialize();
155
156 #elif defined(USE_LINUX_SHARED_LIBRARIES)
157     linux_initialize();
158
159 #else
160     {
161         gss_mechanism mech;
162
163         /*
164          * Use hard-coded in mechanisms...  I need to know what mechanisms
165          * are supported...  As more mechanisms become supported, they
166          * should be added here, unless shared libraries are used.
167          */
168
169         /* Initialize the krb5 mechanism */
170         mech = (gss_mechanism)krb5_gss_initialize();
171         if (mech)
172             add_mechanism (mech, 1);
173     }
174
175 #endif /* USE_SOLARIS_SHARED_LIBRARIES */
176
177 #if !defined(macintosh)
178     if (__gss_mechs_array == NULL) { /* this is very bad! */
179       fprintf(stderr,"gss_initialize fatal error: no mechanisms loaded!\n");
180       exit(-1);
181     }
182 #else
183     /*
184      * Nothing for now, since this should never happen using static
185      * mechanism loading.
186      */
187 #endif
188
189     return;
190 }
191
192 #ifdef USE_SOLARIS_SHARED_LIBRARIES
193 /*
194  * read the configuration file to find out what mechanisms to
195  * load, load them, and then load the mechanism defitions in
196  * and add the mechanisms
197  */
198 static void solaris_initialize ()
199 {
200     char buffer[BUFSIZ], *filename, *symname, *endp;
201     FILE *conffile;
202     void *dl;
203     gss_mechanism (*sym)(void), mech;
204
205     if ((filename = getenv("GSSAPI_MECH_CONF")) == NULL)
206         filename = MECH_CONF;
207
208     if ((conffile = fopen(filename, "r")) == NULL) {
209                 fprintf(stderr,"fatal error: unable to open %s:"
210                         " errno %d (%s)\n", filename, errno, strerror(errno));
211                 return;
212     }
213
214     while (fgets (buffer, BUFSIZ, conffile) != NULL) {
215         /* ignore lines beginning with # */
216         if (*buffer == '#')
217             continue;
218
219         /* find the first white-space character after the filename */
220         for (symname = buffer; *symname && !isspace(*symname); symname++);
221
222         /* Now find the first non-white-space character */
223         if (*symname) {
224             *symname = '\0';
225             symname++;
226             while (*symname && isspace(*symname))
227                 symname++;
228         }
229
230         if (! *symname)
231             symname = MECH_SYM;
232         else {
233           /* Find the end of the symname and make sure it is NULL-terminated */
234           for (endp = symname; *endp && !isspace(*endp); endp++);
235           if (*endp)
236             *endp = '\0';
237         }
238
239         if ((dl = dlopen(buffer, RTLD_NOW)) == NULL) {
240                 /* for debugging only */
241                 fprintf(stderr,"can't open %s: %s\n",buffer, dlerror());
242                 continue;
243         }
244
245         if ((sym = (gss_mechanism (*)(void))dlsym(dl, symname)) == NULL) {
246             dlclose(dl);
247             continue;
248         }
249
250         /* Call the symbol to get the mechanism table */
251         mech = sym();
252
253         /* And add the mechanism (or close the shared library) */
254         if (mech)
255             add_mechanism (mech, 1);
256         else
257             dlclose(dl);
258
259     } /* while */
260
261     return;
262 }
263 #endif /* USE_SOLARIS_SHARED_LIBRARIES */
264
265 #ifdef USE_LINUX_SHARED_LIBRARIES
266 extern gss_mechanism internal_krb5_gss_initialize(void *dl);
267
268 /*
269  * read the configuration file to find out what mechanisms to
270  * load, load them, and then load the mechanism defitions in
271  * and add the mechanisms
272  */
273 static void linux_initialize ()
274 {
275     char buffer[BUFSIZ], *filename, *symname, *endp, *err_string;
276     FILE *conffile;
277     void *dl;
278     gss_mechanism (*sym)(void), mech;
279
280     if ((filename = getenv("GSSAPI_MECH_CONF")) == NULL)
281         filename = MECH_CONF;
282
283     if ((conffile = fopen(filename, "r")) == NULL) {
284                 fprintf(stderr,"fatal error: unable to open %s:"
285                         " errno %d (%s)\n", filename, errno, strerror(errno));
286                 return;
287     }
288
289     while (fgets (buffer, BUFSIZ, conffile) != NULL) {
290         /* ignore lines beginning with # */
291         if (*buffer == '#')
292             continue;
293
294         /* find the first white-space character after the filename */
295         for (symname = buffer; *symname && !isspace(*symname); symname++);
296
297         /* Now find the first non-white-space character */
298         if (*symname) {
299             *symname = '\0';
300             symname++;
301             while (*symname && isspace(*symname))
302                 symname++;
303         }
304
305         if (! *symname)
306             symname = MECH_SYM;
307         else {
308             /* Find the end of the symname and make sure it is
309              * NULL-terminated */
310             for (endp = symname; *endp && !isspace(*endp); endp++);
311             if (*endp)
312                 *endp = '\0';
313         }
314
315         if ((dl = dlopen(buffer, RTLD_NOW)) == NULL) {
316             /* for debugging only */
317             fprintf(stderr,"can't open %s: %s\n",buffer, dlerror());
318             continue;
319         }
320
321 #if defined(HAVE_KRB5) && defined(HAVE_HEIMDAL)
322 #error Should not have both HAVE_KRB5 and HAVE_HEIMDAL defined!!
323 #endif
324
325 #ifdef HAVE_KRB5
326         /* Special case for dealing with MIT krb5 mechanism */
327         if (strcmp(symname, "mechglue_internal_krb5_init") == 0) {
328 #ifdef DEBUG
329             fprintf(stderr, "Using special MIT initialization\n");
330 #endif
331             mech = internal_krb5_gss_initialize(dl);
332         }
333         else
334 #endif
335
336 #ifdef HAVE_HEIMDAL
337         /* Special case for dealing with heimdal krb5 mechanism */
338         if (strcmp(symname, "mechglue_internal_heimdal_init") == 0) {
339 #ifdef DEBUG
340             fprintf(stderr, "Using special Heimdal initialization\n");
341 #endif
342             mech = internal_heimdal_gss_initialize(dl);
343         }
344         else
345 #endif
346         {
347             if ((sym = (gss_mechanism (*)(void))dlsym(dl, symname)) == NULL) {
348                 if ((err_string = dlerror()) != NULL) {
349                     fprintf(stderr, "%s: searching for symbol '%s' in '%s'\n",
350                             err_string, symname, buffer);
351                     dlclose(dl);
352                 }
353                 continue;
354             }
355
356             /* Call the symbol to get the mechanism table */
357             mech = sym();
358         }
359
360         /* And add the mechanism (or close the shared library) */
361         if (mech) {
362 #ifdef DEBUG
363             fprintf(stderr, "Adding mechanism for library '%s'\n", buffer);
364 #endif
365             add_mechanism (mech, 1);
366         }
367         else {
368 #ifdef DEBUG
369             fprintf(stderr,
370                     "Failed to initialize mechanism for library '%s'\n",
371                      buffer);
372 #endif
373             dlclose(dl);
374         }
375
376     } /* while */
377
378     return;
379 }
380 #endif /* USE_LINUX_SHARED_LIBRARIES */