X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=support%2Fgssapi%2Fg_initialize.c;fp=support%2Fgssapi%2Fg_initialize.c;h=9523d40af76d0cb2a80393e95ae4b1c58f9d5b6f;hp=0000000000000000000000000000000000000000;hb=f1bfe0916c04d93de7a4fae5315fff6e4ccac23f;hpb=981d25a37fe4a71eddd162672a658da223453985 diff --git a/support/gssapi/g_initialize.c b/support/gssapi/g_initialize.c new file mode 100644 index 0000000..9523d40 --- /dev/null +++ b/support/gssapi/g_initialize.c @@ -0,0 +1,380 @@ +/* #ident "@(#)g_initialize.c 1.2 96/02/06 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This function will initialize the gssapi mechglue library + */ + +#include "config.h" +#include "mglueP.h" +#ifdef HAVE_STDLIB_H +#include +#endif + +#include +#include +#include +#include + +#ifdef USE_SOLARIS_SHARED_LIBRARIES +#include + +#define MECH_CONF "/etc/mech.conf" +#define MECH_SYM "gss_mech_initialize" + +static void solaris_initialize (void); +#endif /* USE_SOLARIS_SHARED_LIBRARIES */ + +#ifdef __linux__ +#define USE_LINUX_SHARED_LIBRARIES +#endif + +#ifdef USE_LINUX_SHARED_LIBRARIES +#include +#define MECH_CONF "/etc/gssapi_mech.conf" +#define MECH_SYM "gss_mech_initialize" +static void linux_initialize (void); +#endif /* USE_LINUX_SHARED_LIBRARIES */ + +#define g_OID_equal(o1,o2) \ + (((o1)->length == (o2)->length) && \ + (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0)) + +extern gss_mechanism krb5_gss_initialize(); + +static int _gss_initialized = 0; + +static struct gss_config null_mech = { + {0,NULL}}; + +gss_mechanism *__gss_mechs_array = NULL; + +/* + * This function will add a new mechanism to the mechs_array + */ + +static OM_uint32 +add_mechanism (mech, replace) + gss_mechanism mech; + int replace; +{ + gss_mechanism * temp_array; + gss_OID_set mech_names; + OM_uint32 minor_status, major_status; + unsigned int i; + + if (mech == NULL) + return GSS_S_COMPLETE; + + /* initialize the mechs_array if it hasn't already been initialized */ + if (__gss_mechs_array == NULL) { + __gss_mechs_array = (gss_mechanism *) malloc (sizeof(gss_mechanism)); + + if (__gss_mechs_array == NULL) + return ENOMEM; + + __gss_mechs_array[0] = &null_mech; + } + + /* + * Find the length of __gss_mechs_array, and look for an existing + * entry for this OID + */ + for (i=0; __gss_mechs_array[i]->mech_type.length != 0; i++) { + if (!g_OID_equal(&__gss_mechs_array[i]->mech_type, + &mech->mech_type)) + continue; + + /* We found a match. Replace it? */ + if (!replace) + return GSS_S_FAILURE; + + __gss_mechs_array[i] = mech; + return GSS_S_COMPLETE; + } + + /* we didn't find it -- add it to the end of the __gss_mechs_array */ + temp_array = (gss_mechanism *) realloc(__gss_mechs_array, + (i+2)*sizeof(gss_mechanism)); + + if (temp_array == NULL) + return ENOMEM; + + temp_array[i++] = mech; + temp_array[i] = &null_mech; + + __gss_mechs_array = temp_array; + + /* + * OK, now let's register all of the name types this mechanism + * knows how to deal with. + */ + major_status = gss_inquire_names_for_mech(&minor_status, &mech->mech_type, + &mech_names); + if (major_status != GSS_S_COMPLETE) + return (GSS_S_COMPLETE); + for (i=0; i < mech_names->count; i++) { + gss_add_mech_name_type(&minor_status, &mech_names->elements[i], + &mech->mech_type); + } + (void) gss_release_oid_set(&minor_status, &mech_names); + + return GSS_S_COMPLETE; +} + +void gss_initialize () +{ + /* Make sure we've not run already */ + if (_gss_initialized) + return; + _gss_initialized = 1; + +#ifdef USE_SOLARIS_SHARED_LIBRARIES + solaris_initialize(); + +#elif defined(USE_LINUX_SHARED_LIBRARIES) + linux_initialize(); + +#else + { + gss_mechanism mech; + + /* + * Use hard-coded in mechanisms... I need to know what mechanisms + * are supported... As more mechanisms become supported, they + * should be added here, unless shared libraries are used. + */ + + /* Initialize the krb5 mechanism */ + mech = (gss_mechanism)krb5_gss_initialize(); + if (mech) + add_mechanism (mech, 1); + } + +#endif /* USE_SOLARIS_SHARED_LIBRARIES */ + +#if !defined(macintosh) + if (__gss_mechs_array == NULL) { /* this is very bad! */ + fprintf(stderr,"gss_initialize fatal error: no mechanisms loaded!\n"); + exit(-1); + } +#else + /* + * Nothing for now, since this should never happen using static + * mechanism loading. + */ +#endif + + return; +} + +#ifdef USE_SOLARIS_SHARED_LIBRARIES +/* + * read the configuration file to find out what mechanisms to + * load, load them, and then load the mechanism defitions in + * and add the mechanisms + */ +static void solaris_initialize () +{ + char buffer[BUFSIZ], *filename, *symname, *endp; + FILE *conffile; + void *dl; + gss_mechanism (*sym)(void), mech; + + if ((filename = getenv("GSSAPI_MECH_CONF")) == NULL) + filename = MECH_CONF; + + if ((conffile = fopen(filename, "r")) == NULL) { + fprintf(stderr,"fatal error: unable to open %s:" + " errno %d (%s)\n", filename, errno, strerror(errno)); + return; + } + + while (fgets (buffer, BUFSIZ, conffile) != NULL) { + /* ignore lines beginning with # */ + if (*buffer == '#') + continue; + + /* find the first white-space character after the filename */ + for (symname = buffer; *symname && !isspace(*symname); symname++); + + /* Now find the first non-white-space character */ + if (*symname) { + *symname = '\0'; + symname++; + while (*symname && isspace(*symname)) + symname++; + } + + if (! *symname) + symname = MECH_SYM; + else { + /* Find the end of the symname and make sure it is NULL-terminated */ + for (endp = symname; *endp && !isspace(*endp); endp++); + if (*endp) + *endp = '\0'; + } + + if ((dl = dlopen(buffer, RTLD_NOW)) == NULL) { + /* for debugging only */ + fprintf(stderr,"can't open %s: %s\n",buffer, dlerror()); + continue; + } + + if ((sym = (gss_mechanism (*)(void))dlsym(dl, symname)) == NULL) { + dlclose(dl); + continue; + } + + /* Call the symbol to get the mechanism table */ + mech = sym(); + + /* And add the mechanism (or close the shared library) */ + if (mech) + add_mechanism (mech, 1); + else + dlclose(dl); + + } /* while */ + + return; +} +#endif /* USE_SOLARIS_SHARED_LIBRARIES */ + +#ifdef USE_LINUX_SHARED_LIBRARIES +extern gss_mechanism internal_krb5_gss_initialize(void *dl); + +/* + * read the configuration file to find out what mechanisms to + * load, load them, and then load the mechanism defitions in + * and add the mechanisms + */ +static void linux_initialize () +{ + char buffer[BUFSIZ], *filename, *symname, *endp, *err_string; + FILE *conffile; + void *dl; + gss_mechanism (*sym)(void), mech; + + if ((filename = getenv("GSSAPI_MECH_CONF")) == NULL) + filename = MECH_CONF; + + if ((conffile = fopen(filename, "r")) == NULL) { + fprintf(stderr,"fatal error: unable to open %s:" + " errno %d (%s)\n", filename, errno, strerror(errno)); + return; + } + + while (fgets (buffer, BUFSIZ, conffile) != NULL) { + /* ignore lines beginning with # */ + if (*buffer == '#') + continue; + + /* find the first white-space character after the filename */ + for (symname = buffer; *symname && !isspace(*symname); symname++); + + /* Now find the first non-white-space character */ + if (*symname) { + *symname = '\0'; + symname++; + while (*symname && isspace(*symname)) + symname++; + } + + if (! *symname) + symname = MECH_SYM; + else { + /* Find the end of the symname and make sure it is + * NULL-terminated */ + for (endp = symname; *endp && !isspace(*endp); endp++); + if (*endp) + *endp = '\0'; + } + + if ((dl = dlopen(buffer, RTLD_NOW)) == NULL) { + /* for debugging only */ + fprintf(stderr,"can't open %s: %s\n",buffer, dlerror()); + continue; + } + +#if defined(HAVE_KRB5) && defined(HAVE_HEIMDAL) +#error Should not have both HAVE_KRB5 and HAVE_HEIMDAL defined!! +#endif + +#ifdef HAVE_KRB5 + /* Special case for dealing with MIT krb5 mechanism */ + if (strcmp(symname, "mechglue_internal_krb5_init") == 0) { +#ifdef DEBUG + fprintf(stderr, "Using special MIT initialization\n"); +#endif + mech = internal_krb5_gss_initialize(dl); + } + else +#endif + +#ifdef HAVE_HEIMDAL + /* Special case for dealing with heimdal krb5 mechanism */ + if (strcmp(symname, "mechglue_internal_heimdal_init") == 0) { +#ifdef DEBUG + fprintf(stderr, "Using special Heimdal initialization\n"); +#endif + mech = internal_heimdal_gss_initialize(dl); + } + else +#endif + { + if ((sym = (gss_mechanism (*)(void))dlsym(dl, symname)) == NULL) { + if ((err_string = dlerror()) != NULL) { + fprintf(stderr, "%s: searching for symbol '%s' in '%s'\n", + err_string, symname, buffer); + dlclose(dl); + } + continue; + } + + /* Call the symbol to get the mechanism table */ + mech = sym(); + } + + /* And add the mechanism (or close the shared library) */ + if (mech) { +#ifdef DEBUG + fprintf(stderr, "Adding mechanism for library '%s'\n", buffer); +#endif + add_mechanism (mech, 1); + } + else { +#ifdef DEBUG + fprintf(stderr, + "Failed to initialize mechanism for library '%s'\n", + buffer); +#endif + dlclose(dl); + } + + } /* while */ + + return; +} +#endif /* USE_LINUX_SHARED_LIBRARIES */