]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - support/gssapi/g_mit_krb5_mech.c
Add gss support from citi @ umich
[nfs-utils.git] / support / gssapi / g_mit_krb5_mech.c
diff --git a/support/gssapi/g_mit_krb5_mech.c b/support/gssapi/g_mit_krb5_mech.c
new file mode 100644 (file)
index 0000000..1caa8d2
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ *  g_mit_krb5_mech.c
+ *
+ *  Copyright (c) 2004 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Kevin Coffman <kwc@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <dlfcn.h>
+#include "mglueP.h"
+
+/*
+ * Table of function names that we need to locate within a mechanism's
+ * shared library if it does not support the xxx_gss_initialize function.
+ */
+static char *glue_func_names[] = {
+       "gss_acquire_cred",
+       "gss_release_cred",
+       "gss_init_sec_context",
+       "gss_accept_sec_context",
+       "gss_process_context_token",
+       "gss_delete_sec_context",
+       "gss_context_time",
+       "gss_sign",
+       "gss_verify",
+       "gss_seal",
+       "gss_unseal",
+       "gss_display_status",
+       "gss_indicate_mechs",
+       "gss_compare_name",
+       "gss_display_name",
+       "gss_import_name",
+       "gss_release_name",
+       "gss_inquire_cred",
+       "gss_add_cred",
+       "gss_export_sec_context",
+       "gss_import_sec_context",
+       "gss_inquire_cred_by_mech",
+       "gss_inquire_names_for_mech",
+       "gss_inquire_context",
+       "gss_internal_release_oid",
+       "gss_wrap_size_limit",
+       "pname_to_uid",
+       "gss_duplicate_name",
+       "gss_set_allowable_enctypes",
+       "gss_verify_mic",
+       NULL
+};
+
+#ifdef HAVE_KRB5
+/*
+ * The MIT code does not support the krb5_gss_initialize function, so
+ * we need to locate the functions within the gssapi_krb5.so library
+ * and fill in this structure.
+ */
+static struct gss_config mit_krb5_mechanism = {
+       {9, "\052\206\110\206\367\022\001\002\002"},
+       NULL,           /* mechanism context -- we don't currently use this */
+       NULL,           /* gss_acquire_cred */
+       NULL,           /* gss_release_cred */
+       NULL,           /* gss_init_sec_context */
+       NULL,           /* gss_accept_sec_context */
+       NULL,           /* gss_process_context_token */
+       NULL,           /* gss_delete_sec_context */
+       NULL,           /* gss_context_time */
+       NULL,           /* gss_sign */
+       NULL,           /* gss_verify */
+       NULL,           /* gss_seal */
+       NULL,           /* gss_unseal */
+       NULL,           /* gss_display_status */
+       NULL,           /* gss_indicate_mechs */
+       NULL,           /* gss_compare_name */
+       NULL,           /* gss_display_name */
+       NULL,           /* gss_import_name */
+       NULL,           /* gss_release_name */
+       NULL,           /* gss_inquire_cred */
+       NULL,           /* gss_add_cred */
+       NULL,           /* gss_export_sec_context */
+       NULL,           /* gss_import_sec_context */
+       NULL,           /* gss_inquire_cred_by_mech */
+       NULL,           /* gss_inquire_names_for_mech */
+       NULL,           /* gss_inquire_context */
+       NULL,           /* gss_internal_release_oid */
+       NULL,           /* gss_wrap_size_limit */
+       NULL,           /* pname_to_uid */
+       NULL,           /* gss_duplicate_name */
+       NULL,           /* gss_set_allowable_enctypes */
+       NULL,           /* gss_verify_mic */
+};
+#endif
+
+#ifdef HAVE_HEIMDAL
+/*
+ * The heimdal code does not support the krb5_gss_initialize function, so
+ * we need to locate the functions within the libgssapi.so library
+ * and fill in this structure.
+ */
+static struct gss_config heimdal_krb5_mechanism = {
+       {9, "\052\206\110\206\367\022\001\002\002"},
+       NULL,           /* mechanism context -- we don't currently use this */
+       NULL,           /* gss_acquire_cred */
+       NULL,           /* gss_release_cred */
+       NULL,           /* gss_init_sec_context */
+       NULL,           /* gss_accept_sec_context */
+       NULL,           /* gss_process_context_token */
+       NULL,           /* gss_delete_sec_context */
+       NULL,           /* gss_context_time */
+       NULL,           /* gss_sign */
+       NULL,           /* gss_verify */
+       NULL,           /* gss_seal */
+       NULL,           /* gss_unseal */
+       NULL,           /* gss_display_status */
+       NULL,           /* gss_indicate_mechs */
+       NULL,           /* gss_compare_name */
+       NULL,           /* gss_display_name */
+       NULL,           /* gss_import_name */
+       NULL,           /* gss_release_name */
+       NULL,           /* gss_inquire_cred */
+       NULL,           /* gss_add_cred */
+       NULL,           /* gss_export_sec_context */
+       NULL,           /* gss_import_sec_context */
+       NULL,           /* gss_inquire_cred_by_mech */
+       NULL,           /* gss_inquire_names_for_mech */
+       NULL,           /* gss_inquire_context */
+       NULL,           /* gss_internal_release_oid */
+       NULL,           /* gss_wrap_size_limit */
+       NULL,           /* pname_to_uid */
+       NULL,           /* gss_duplicate_name */
+       NULL,           /* gss_set_allowable_enctypes */
+       NULL,           /* gss_verify_mic */
+};
+#endif
+
+
+/*
+ * Given a handle to a dynamic library (dl) and a symbol
+ * name (symname), return its address.  Returns -1 if the
+ * symbol cannot be located.  (Note that the value of the
+ * symbol could be NULL, which is valid.)
+ */
+void *
+locate_symbol(void *dl, char *symname, char *prefix)
+{
+       void *sym;
+       const char *err_string;
+       char fullname[256];
+
+       snprintf(fullname, sizeof(fullname), "%s%s", prefix, symname);
+
+       if ((sym = dlsym(dl, fullname)) == NULL) {
+               if ((sym = dlsym(dl, symname)) == NULL) {
+                       if ((err_string = dlerror()) != NULL) {
+                               return (void *)-1;
+                       }
+                       else {
+                               return NULL;
+                       }
+               }
+       }
+       return sym;
+}
+
+#ifdef HAVE_KRB5
+/*
+ * Locate all the symbols in the MIT gssapi library and
+ * fill in the gss_config (gss_mechanism) structure.
+ */
+gss_mechanism
+internal_krb5_gss_initialize(void *dl)
+{
+       char *fname;
+       void *p;
+       void **fptr;
+       int i;
+       static int mit_krb5_initialized = 0;
+
+       if (mit_krb5_initialized)
+               return (&mit_krb5_mechanism);
+
+       fptr = (void *) &mit_krb5_mechanism.gss_acquire_cred;
+
+
+       for (i = 0, fname = glue_func_names[i];
+            fname;
+            i++, fname = glue_func_names[i]) {
+               if ((p = locate_symbol(dl, fname, "krb5_")) != (void *)-1) {
+                       *fptr++ = p;
+               }
+               else {
+                       *fptr++ = NULL;
+               }
+       }
+       if (mit_krb5_mechanism.gss_internal_release_oid == NULL ||
+           mit_krb5_mechanism.gss_internal_release_oid == (void *) -1) {
+           fprintf(stderr, "WARNING: unable to locate function "
+               "krb5_gss_internal_release_oid in krb5 mechanism library: "
+               "there will be problems if multiple mechanisms are used!\n");
+           p = locate_symbol(dl, "krb5_gss_release_oid", "");
+           if (p == NULL || p == (void *) -1) {
+               fprintf(stderr, "ERROR: Unable to locate function "
+                       "krb5_gss_internal_release_oid or "
+                       "krb5_gss_release_oid in krb5 mechanism library\n");
+               return NULL;
+           }
+       }
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+       /*
+        * Special case for set_allowable_enctypes which has a different
+        * name format than the rest of the gss routines :-/
+        */
+       if ((p = locate_symbol(dl, "gss_krb5_set_allowable_enctypes", ""))
+                                                       != (void *)-1) {
+               mit_krb5_mechanism.gss_set_allowable_enctypes = p;
+       }
+#endif
+       mit_krb5_initialized = 1;
+       return (&mit_krb5_mechanism);
+}
+#endif
+
+#ifdef HAVE_HEIMDAL
+/*
+ * Locate all the symbols in the MIT gssapi library and
+ * fill in the gss_config (gss_mechanism) structure.
+ */
+gss_mechanism
+internal_heimdal_gss_initialize(void *dl)
+{
+       char *fname;
+       void *p;
+       void **fptr;
+       int i;
+       static int heimdal_krb5_initialized = 0;
+
+       if (heimdal_krb5_initialized)
+               return (&heimdal_krb5_mechanism);
+
+       fptr = (void *) &heimdal_krb5_mechanism.gss_acquire_cred;
+
+
+       for (i = 0, fname = glue_func_names[i];
+            fname;
+            i++, fname = glue_func_names[i]) {
+               if ((p = locate_symbol(dl, fname, "")) != (void *)-1) {
+                       *fptr++ = p;
+               }
+               else {
+printf("Failed to locate function '%s' !!!\n", fname);
+                       *fptr++ = NULL;
+               }
+       }
+       if (heimdal_krb5_mechanism.gss_internal_release_oid == NULL ||
+           heimdal_krb5_mechanism.gss_internal_release_oid == (void *) -1) {
+           fprintf(stderr, "WARNING: unable to locate function "
+               "gss_internal_release_oid in krb5 mechanism library: "
+               "there will be problems if multiple mechanisms are used!\n");
+           p = locate_symbol(dl, "krb5_gss_release_oid", "");
+           if (p == NULL || p == (void *) -1) {
+               fprintf(stderr, "ERROR: Unable to locate function "
+                       "gss_internal_release_oid or "
+                       "gss_release_oid in krb5 mechanism library\n");
+               return NULL;
+           }
+       }
+       heimdal_krb5_initialized = 1;
+       return (&heimdal_krb5_mechanism);
+}
+#endif