]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Changed to krb5int_open_plugin_dirs/krb5int_close_plugin_dirs which
authorAlexandra Ellwood <lxs@mit.edu>
Thu, 4 May 2006 03:06:33 +0000 (03:06 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Thu, 4 May 2006 03:06:33 +0000 (03:06 +0000)
takes a list of filebases and directories rather than a list of full paths
so the caller doesn't have to generate the possibilities themselves.
krb5int_open_plugin_dirs will append the possible suffixes for that platform
(including no suffix in case there already is one on the file base).

Modified the kdb and locate kdc interfaces to use the new API.

ticket: 3716

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17975 dc483132-0cff-0310-8789-dd5450dbe970

src/include/k5-plugin.h
src/include/stock/osconf.h
src/lib/kdb/kdb5.c
src/lib/kdb/kdb5.h
src/lib/krb5/os/init_os_ctx.c
src/lib/krb5/os/locate_kdc.c
src/util/support/plugins.c

index c7fb1776ca32f2cb841687cf90c400a9a54dbace..5bb9be7a0036393b855833b546ffad1a4d0af7aa 100644 (file)
@@ -72,8 +72,9 @@ struct plugin_dir_handle {
 #define PLUGIN_DIR_OPEN(P) ((P)->files != NULL)
 
 long KRB5_CALLCONV
-krb5int_open_plugin (const char *, struct plugin_file_handle **,
-                    struct errinfo *);
+krb5int_open_plugin (const char *, struct plugin_file_handle **, struct errinfo *);
+void KRB5_CALLCONV
+krb5int_close_plugin (struct plugin_file_handle *);
 
 long KRB5_CALLCONV
 krb5int_get_plugin_data (struct plugin_file_handle *, const char *, void **,
@@ -83,18 +84,21 @@ long KRB5_CALLCONV
 krb5int_get_plugin_func (struct plugin_file_handle *, const char *,
                         void (**)(), struct errinfo *);
 
-void KRB5_CALLCONV
-krb5int_close_plugin (struct plugin_file_handle *);
 
-long KRB5_CALLCONV krb5int_open_plugin_dir (const char *,
-                                           struct plugin_dir_handle *,
-                                           struct errinfo *);
-void KRB5_CALLCONV krb5int_close_plugin_dir (struct plugin_dir_handle *);
-void KRB5_CALLCONV krb5int_free_plugin_dir_data (void **);
-long KRB5_CALLCONV krb5int_get_plugin_dir_data (struct plugin_dir_handle *,
-                                               const char *, void ***,
-                                               struct errinfo *);
-void KRB5_CALLCONV krb5int_free_plugin_dir_func (void (**)(void));
-long KRB5_CALLCONV krb5int_get_plugin_dir_func (struct plugin_dir_handle *,
-                                               const char *, void (***)(void),
-                                               struct errinfo *);
+long KRB5_CALLCONV
+krb5int_open_plugin_dirs (const char * const *, const char * const *,
+                         struct plugin_dir_handle *, struct errinfo *);
+void KRB5_CALLCONV 
+krb5int_close_plugin_dirs (struct plugin_dir_handle *);
+
+long KRB5_CALLCONV 
+krb5int_get_plugin_dir_data (struct plugin_dir_handle *, const char *, 
+                            void ***, struct errinfo *);
+void KRB5_CALLCONV 
+krb5int_free_plugin_dir_data (void **);
+
+long KRB5_CALLCONV 
+krb5int_get_plugin_dir_func (struct plugin_dir_handle *, const char *, 
+                            void (***)(void), struct errinfo *);
+void KRB5_CALLCONV 
+krb5int_free_plugin_dir_func (void (**)(void));
index 03b2ce651d60a1502c2b2d834c3e1dc0a0602b3f..26a28054e65ee6598bdd248fd53892d94e694f7f 100644 (file)
 #define        DEFAULT_KDC_PROFILE     "@LOCALSTATEDIR/krb5kdc/kdc.conf"
 #define        KDC_PROFILE_ENV         "KRB5_KDC_PROFILE"
 
+#if TARGET_OS_MAC
+#define DEFAULT_KDB_LIB_PATH   { KDB5_PLUGIN_BUNDLE_DIR, "@MODULEDIR/kdb", NULL }
+#else
 #define DEFAULT_KDB_LIB_PATH   { "@MODULEDIR/kdb", NULL }
+#endif
 #define MODULE_PATH            "@MODULEDIR"
 
 #define        DEFAULT_KDC_ENCTYPE     ENCTYPE_DES3_CBC_SHA1
index 51c31200d305da539b7a54a8f35fcea8ac267838..c6225474a9b20fdb98c783bbc85ec36bc55d95d1 100644 (file)
@@ -161,7 +161,7 @@ kdb_get_library_name(krb5_context kcontext)
        goto clean_n_exit;
     }
 
-#define DB2_NAME "db2.so"
+#define DB2_NAME "db2"
     /* we got the module section. Get the library name from the module */
     status = profile_get_string(kcontext->profile, KDB_MODULE_SECTION, value,
                                KDB_LIB_POINTER,
@@ -301,10 +301,8 @@ static krb5_error_code
 kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
 {
     krb5_error_code status = 0;
-    char    dl_name[1024];
     int     ndx;
-    void   *vftabl_addr;
-    char   *err_str = NULL;
+    void  **vftabl_addrs = NULL;
     /* N.B.: If this is "const" but not "static", the Solaris 10
        native compiler has trouble building the library because of
        absolute relocations needed in read-only section ".rodata".
@@ -313,6 +311,7 @@ kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
     static const char *const dbpath_names[] = {
        KDB_MODULE_SECTION, "db_module_dir", NULL,
     };
+    const char *filebases[] = { lib_name, NULL };
     char **profpath = NULL;
     char **path = NULL;
 
@@ -353,60 +352,55 @@ kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
        memcpy(path, profpath, ndx * sizeof(profpath[0]));
     memcpy(path + ndx, db_dl_location, db_dl_n_locations * sizeof(char *));
     status = 0;
+    
+    if ((status = krb5int_open_plugin_dirs ((const char **) path, 
+                                            filebases, 
+                                            &(*lib)->dl_dir_handle, &kcontext->err))) {
+        char *err_str = krb5_get_error_message(kcontext, status);
+       status = KRB5_KDB_DBTYPE_NOTFOUND;
+       krb5_set_error_message (kcontext, status,
+                               "Unable to find requested database type: %s", err_str);
+       krb5_free_error_message (kcontext, err_str);
+       goto clean_n_exit;
+    }
 
-    for (ndx = 0; path[ndx]; ndx++) {
-       sprintf(dl_name, "%s/%s", path[ndx], lib_name);
-       status = krb5int_open_plugin (dl_name, &(*lib)->dl_handle,
-                                     &kcontext->err);
-       if (status == 0) {
-           /* found the module */
-           status = krb5int_get_plugin_data((*lib)->dl_handle,
-                                            "kdb_function_table",
-                                            &vftabl_addr, &kcontext->err);
-           if (status == 0) {
-               memcpy(&(*lib)->vftabl, vftabl_addr, sizeof(kdb_vftabl));
-
-               kdb_setup_opt_functions(*lib);
-
-               if ((status = (*lib)->vftabl.init_library())) {
-                   /* ERROR. library not initialized cleanly */
-                   goto clean_n_exit;
-               }
-           } else {
-               const char *emsg = krb5_get_error_message (kcontext, status);
-               status = KRB5_KDB_DBTYPE_INIT;
-               krb5_set_error_message (kcontext, status,
-                                       "plugin symbol 'kdb_function_table' lookup failed: %s",
-                                       dl_name, emsg);
-               krb5_free_error_message (kcontext, emsg);
-               goto clean_n_exit;
-           }
-           break;
-       } else {
-           err_str = krb5_get_error_message(kcontext, status);
-       }
+    if ((status = krb5int_get_plugin_dir_data (&(*lib)->dl_dir_handle, "kdb_function_table",
+                                               &vftabl_addrs, &kcontext->err))) {
+        char *err_str = krb5_get_error_message(kcontext, status);
+        status = KRB5_KDB_DBTYPE_INIT;
+        krb5_set_error_message (kcontext, status,
+                                "plugin symbol 'kdb_function_table' lookup failed: %s", err_str);
+        krb5_free_error_message (kcontext, err_str);
+       goto clean_n_exit;
     }
 
-    if (!(*lib)->dl_handle) {
-       /* library not found in the given list. Error str is already set */
+    if (vftabl_addrs[0] == NULL) {
+       /* No plugins! */
        status = KRB5_KDB_DBTYPE_NOTFOUND;
-       krb5_set_error_message (kcontext, status,
-                               _("Unable to find requested database type: %s"),
-                               err_str);
-       krb5_free_error_message (kcontext, err_str);
+       krb5_set_error_message (kcontext, status, 
+                                "Unable to find requested database type");
        goto clean_n_exit;
     }
 
-  clean_n_exit:
+    memcpy(&(*lib)->vftabl, vftabl_addrs[0], sizeof(kdb_vftabl));
+    kdb_setup_opt_functions(*lib);
+    
+    if ((status = (*lib)->vftabl.init_library())) {
+        /* ERROR. library not initialized cleanly */
+        goto clean_n_exit;
+    }    
+    
+clean_n_exit:
+    if (vftabl_addrs != NULL) { krb5int_free_plugin_dir_data (vftabl_addrs); }
     /* Both of these DTRT with NULL.  */
     profile_free_list(profpath);
     free(path);
     if (status) {
-       if (*lib) {
+        if (*lib) {
            kdb_destroy_lib_lock(*lib);
-           if ((*lib)->dl_handle) {
-               krb5int_close_plugin((*lib)->dl_handle);
-           }
+            if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle))) {
+                krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle);
+            }
            free(*lib);
            *lib = NULL;
        }
@@ -485,10 +479,10 @@ kdb_free_library(db_library lib)
        }
 
        /* close the library */
-       if (lib->dl_handle) {
-           krb5int_close_plugin(lib->dl_handle);
-       }
-
+        if (PLUGIN_DIR_OPEN((&lib->dl_dir_handle))) {
+            krb5int_close_plugin_dirs (&lib->dl_dir_handle);
+        }
+        
        kdb_destroy_lib_lock(lib);
 
        if (lib->prev == NULL) {
index a522ac686d1ad9f09e5af7691bd48e5bd50d2cb5..9b6d1c70c1663a89fd8383a55f90b65ebdbff7b5 100644 (file)
@@ -181,7 +181,7 @@ typedef struct _kdb_vftabl{
 typedef struct _db_library {
     char name[KDB_MAX_DB_NAME];
     int reference_cnt;
-    struct plugin_file_handle *dl_handle;
+    struct plugin_dir_handle dl_dir_handle;
     kdb_vftabl vftabl;
     struct _db_library *next, *prev;
 } *db_library;
index e91a05ff1cf3aacbe98b0cc18331ef5e351fc552..8660389402972382665881fc1c14bbf4c3acdae1 100644 (file)
@@ -481,7 +481,7 @@ krb5_os_free_context(krb5_context ctx)
            ctx->profile = 0;
        }
 
-       krb5int_close_plugin_dir (&ctx->libkrb5_plugins);
+       krb5int_close_plugin_dirs (&ctx->libkrb5_plugins);
 
 #ifdef _WIN32
         WSACleanup();
index 83b0066340d8ff328cf4ea0ebf7f235bac96e963..979337a35d5d92772e9ec35648230d41e59c82b2 100644 (file)
@@ -545,10 +545,10 @@ krb5_locate_srv_dns_1 (const krb5_data *realm,
 
 #include "k5-locate.h"
 
-#ifdef KFM_FRAMEWORK_PLUGIN_DIR
-static const char objdir[] = KFM_FRAMEWORK_PLUGIN_DIR ;
+#if TARGET_OS_MAC
+static const char *objdirs[] = { KRB5_PLUGIN_BUNDLE_DIR, LIBDIR "/krb5/plugins/libkrb5", NULL }; /* should be a list */
 #else
-static const char objdir[] = LIBDIR "/krb5/plugins/libkrb5";
+static const char *objdirs[] = { LIBDIR "/krb5/plugins/libkrb5", NULL };
 #endif
 
 struct module_callback_data {
@@ -612,8 +612,9 @@ module_locate_server (krb5_context ctx, const krb5_data *realm,
     Tprintf("in module_locate_server\n");
     cbdata.lp = addrlist;
     if (!PLUGIN_DIR_OPEN (&ctx->libkrb5_plugins)) {
-       code = krb5int_open_plugin_dir (objdir, &ctx->libkrb5_plugins,
-                                       &ctx->err);
+        
+       code = krb5int_open_plugin_dirs (objdirs, NULL, &ctx->libkrb5_plugins,
+                                        &ctx->err);
        if (code)
            return KRB5_PLUGIN_NO_HANDLE;
     }
index a4780f38faf8476e933f1b1376299bd2ffbf0489..929d94fa4f6d4308fed698e0d9fc87da73e750c1 100644 (file)
@@ -73,8 +73,7 @@ struct plugin_file_handle {
 };
 
 long KRB5_CALLCONV
-krb5int_open_plugin (const char *filename, struct plugin_file_handle **h,
-                    struct errinfo *ep)
+krb5int_open_plugin (const char *filepath, struct plugin_file_handle **h, struct errinfo *ep)
 {
     long err = 0;
     struct stat statbuf;
@@ -82,8 +81,8 @@ krb5int_open_plugin (const char *filename, struct plugin_file_handle **h,
     int got_plugin = 0;
 
     if (!err) {
-        if (stat (filename, &statbuf) < 0) {
-            Tprintf ("stat(%s): %s\n", filename, strerror (errno));
+        if (stat (filepath, &statbuf) < 0) {
+            Tprintf ("stat(%s): %s\n", filepath, strerror (errno));
             err = errno;
         }
     }
@@ -98,10 +97,10 @@ krb5int_open_plugin (const char *filename, struct plugin_file_handle **h,
         void *handle = NULL;
 
         if (!err) {
-            handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL);
+            handle = dlopen(filepath, RTLD_NOW | RTLD_GLOBAL);
             if (handle == NULL) {
                 const char *e = dlerror();
-                Tprintf ("dlopen(%s): %s\n", filename, e);
+                Tprintf ("dlopen(%s): %s\n", filepath, e);
                 err = ENOENT; /* XXX */
                krb5int_set_error (ep, err, "%s", e);
             }
@@ -124,7 +123,7 @@ krb5int_open_plugin (const char *filename, struct plugin_file_handle **h,
         CFBundleRef pluginBundle = NULL;
 
         if (!err) {
-            pluginPath = CFStringCreateWithCString (kCFAllocatorDefault, filename
+            pluginPath = CFStringCreateWithCString (kCFAllocatorDefault, filepath
                                                     kCFStringEncodingASCII);
             if (pluginPath == NULL) { err = ENOMEM; }
         }
@@ -288,74 +287,216 @@ krb5int_close_plugin (struct plugin_file_handle *h)
     (strerror (ERR))
 #endif
 
+static long
+krb5int_plugin_file_handle_array_init (struct plugin_file_handle ***harray)
+{
+    long err = 0;
+
+    *harray = calloc (1, sizeof (**harray)); /* calloc initializes to NULL */
+    if (*harray == NULL) { err = errno; }
+
+    return err;
+}
+
+static long
+krb5int_plugin_file_handle_array_add (struct plugin_file_handle ***harray, int *count, 
+                                      struct plugin_file_handle *p)
+{
+    long err = 0;
+    struct plugin_file_handle **newharray = NULL;
+    int newcount = *count + 1;
+    
+    newharray = realloc (*harray, ((newcount + 1) * sizeof (**harray))); /* +1 for NULL */
+    if (newharray == NULL) { 
+        err = errno; 
+    } else {
+        newharray[newcount - 1] = p;
+        newharray[newcount] = NULL;
+       *count = newcount;
+        *harray = newharray;
+    }
+
+    return err;    
+}
+
+static void
+krb5int_plugin_file_handle_array_free (struct plugin_file_handle **harray)
+{
+    if (harray != NULL) {
+        int i;
+        for (i = 0; harray[i] != NULL; i++) {
+            krb5int_close_plugin (harray[i]);
+        }
+        free (harray);
+    }
+}
+
+#if TARGET_OS_MAC
+#define FILEEXTS { "", ".bundle", ".so", NULL }
+#elif defined(_WIN32)
+#define FILEEXTS  { "", ".dll", NULL };
+#else
+#define FILEEXTS  { "", ".so", NULL };
+#endif
+
+
+static void 
+krb5int_free_plugin_filenames (char **filenames)
+{
+    if (filenames != NULL) { 
+        int i;
+        for (i = 0; filenames[i] != NULL; i++) {
+            free (filenames[i]);
+        }
+        free (filenames); 
+    }    
+}
+
+
+static long 
+krb5int_get_plugin_filenames (const char * const *filebases, char ***filenames)
+{
+    long err = 0;
+    const char *fileexts[] = FILEEXTS;
+    char **tempnames = NULL;
+    int i;
+    
+    if (!err) {
+        size_t count = 0;
+        for (i = 0; filebases[i] != NULL; i++, count++);
+        for (i = 0; fileexts[i] != NULL; i++, count++);
+        tempnames = calloc (count, sizeof (char *));
+        if (tempnames == NULL) { err = errno; }
+    }
+    
+    if (!err) {
+        int i,j;
+        for (i = 0; !err && (filebases[i] != NULL); i++) {
+            size_t baselen = strlen (filebases[i]);
+            for (j = 0; !err && (fileexts[j] != NULL); j++) {
+                size_t len = baselen + strlen (fileexts[j]) + 2; /* '.' + NULL */
+                tempnames[i+j] = malloc (len * sizeof (char));
+                if (tempnames[i+j] == NULL) { 
+                    err = errno; 
+                } else {
+                    sprintf (tempnames[i+j], "%s%s", filebases[i], fileexts[j]);
+                }
+            }
+        }
+    }
+    
+    if (!err) {
+        *filenames = tempnames;
+        tempnames = NULL;
+    }
+    
+    if (tempnames != NULL) { krb5int_free_plugin_filenames (tempnames); }
+    
+    return err;
+}
+
+
+/* Takes a NULL-terminated list of directories.  If filebases is NULL, filebases is ignored
+ * all plugins in the directories are loaded.  If filebases is a NULL-terminated array of names, 
+ * only plugins in the directories with those name (plus any platform extension) are loaded. */
+
 long KRB5_CALLCONV
-krb5int_open_plugin_dir (const char *dirname,
-                        struct plugin_dir_handle *dirhandle,
-                        struct errinfo *ep)
+krb5int_open_plugin_dirs (const char * const *dirnames,
+                          const char * const *filebases,
+                         struct plugin_dir_handle *dirhandle,
+                          struct errinfo *ep)
 {
     long err = 0;
-    DIR *dir = NULL;
-    struct dirent *d = NULL;
     struct plugin_file_handle **h = NULL;
     int count = 0;
+    char **filenames = NULL;
+    int i;
 
     if (!err) {
-        h = calloc (1, sizeof (*h)); /* calloc initializes to NULL */
-        if (h == NULL) { err = errno; }
+        err = krb5int_plugin_file_handle_array_init (&h);
     }
     
-    if (!err) {
-        dir = opendir(dirname);
-        if (dir == NULL) {
-            err = errno;
-            Tprintf ("-> error %d/%s\n", err, strerror (err));
-        }
+    if (!err && (filebases != NULL)) {
+       err = krb5int_get_plugin_filenames (filebases, &filenames);
     }
     
-    while (!err) {
-        size_t len = 0;
-        char *path = NULL;
-        struct plugin_file_handle *handle = NULL;
-        
-        d = readdir (dir);
-       if (d == NULL) { break; }
-        
-        if ((strcmp (d->d_name, ".") == 0) || 
-            (strcmp (d->d_name, "..") == 0)) {
-            continue;
-        }
-        
-        if (!err) {
-            len = NAMELEN (d);
-            path = malloc (strlen (dirname) + len + 2); /* '/' and NULL */
-            if (path == NULL) { 
-                err = errno; 
-            } else {
-                sprintf (path, "%s/%*s", dirname, (int) len, d->d_name);
+    for (i = 0; !err && dirnames[i] != NULL; i++) {
+       size_t dirnamelen = strlen (dirnames[i]) + 1; /* '/' */
+        if (filenames != NULL) {
+            /* load plugins with names from filenames from each directory */
+            int j;
+            
+            for (j = 0; !err && filenames[j] != NULL; j++) {
+                struct plugin_file_handle *handle = NULL;
+               char *filepath = NULL;
+               
+               if (!err) {
+                   filepath = malloc (dirnamelen + strlen (filenames[j]) + 1); /* NULL */
+                   if (filepath == NULL) { 
+                       err = errno; 
+                   } else {
+                       sprintf (filepath, "%s/%s", dirnames[i], filenames[j]);
+                   }
+               }
+               
+                if (krb5int_open_plugin (filepath, &handle, ep) == 0) {
+                    err = krb5int_plugin_file_handle_array_add (&h, &count, handle);
+                    if (!err) { handle = NULL; }  /* h takes ownership */
+                }
+                
+               if (filepath != NULL) { free (filepath); }
+               if (handle   != NULL) { krb5int_close_plugin (handle); }
             }
-        }
-        
-        if (!err) {            
-            if (krb5int_open_plugin (path, &handle, ep) == 0) {
-                struct plugin_file_handle **newh = NULL;
-
-                count++;
-                newh = realloc (h, ((count + 1) + sizeof (*h))); /* +1 for NULL */
-                if (newh == NULL) { 
-                    err = errno; 
-                } else {
-                    h = newh;
-                    h[count - 1] = handle;
-                    h[count] = NULL;
-                    handle = NULL;  /* h takes ownership */
+        } else {
+            /* load all plugins in each directory */
+            DIR *dir = NULL;
+            
+            if (!err) {
+                dir = opendir(dirnames[i]);
+                if (dir == NULL) {
+                    err = errno;
+                    Tprintf ("-> error %d/%s\n", err, strerror (err));
                 }
             }
+            
+            while (!err) {
+                struct dirent *d = NULL;
+                char *filepath = NULL;
+                struct plugin_file_handle *handle = NULL;
+                
+                d = readdir (dir);
+                if (d == NULL) { break; }
+                
+                if ((strcmp (d->d_name, ".") == 0) || 
+                    (strcmp (d->d_name, "..") == 0)) {
+                    continue;
+                }
+                
+               if (!err) {
+                    int len = NAMELEN (d);
+                   filepath = malloc (dirnamelen + len + 1); /* NULL */
+                   if (filepath == NULL) { 
+                       err = errno; 
+                   } else {
+                       sprintf (filepath, "%s/%*s", dirnames[i], len, d->d_name);
+                   }
+               }
+                
+                if (!err) {            
+                    if (krb5int_open_plugin (filepath, &handle, ep) == 0) {
+                        err = krb5int_plugin_file_handle_array_add (&h, &count, handle);
+                        if (!err) { handle = NULL; }  /* h takes ownership */
+                    }
+                }
+                
+                if (filepath  != NULL) { free (filepath); }
+                if (handle    != NULL) { krb5int_close_plugin (handle); }
+            }
+            
+            if (dir != NULL) { closedir (dir); }
         }
-        
-        if (path   != NULL) { free (path); }
-        if (handle != NULL) { krb5int_close_plugin (handle); }
     }
-    
+        
     if (err == ENOENT) {
         err = 0;  /* ran out of plugins -- do nothing */
     }
@@ -365,20 +506,14 @@ krb5int_open_plugin_dir (const char *dirname,
         h = NULL;  /* dirhandle->files takes ownership */
     }
     
-    if (h != NULL) {
-        int i;
-        for (i = 0; h[i] != NULL; i++) {
-            krb5int_close_plugin (h[i]);
-        }
-        free (h);
-    }
-    if (dir != NULL) { closedir (dir); }
+    if (filenames != NULL) { krb5int_free_plugin_filenames (filenames); }
+    if (h         != NULL) { krb5int_plugin_file_handle_array_free (h); }
     
     return err;
 }
 
 void KRB5_CALLCONV
-krb5int_close_plugin_dir (struct plugin_dir_handle *dirhandle)
+krb5int_close_plugin_dirs (struct plugin_dir_handle *dirhandle)
 {
     if (dirhandle->files != NULL) {
         int i;