summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/k5-plugin.h36
-rw-r--r--src/include/stock/osconf.h4
-rw-r--r--src/lib/kdb/kdb5.c94
-rw-r--r--src/lib/kdb/kdb5.h2
-rw-r--r--src/lib/krb5/os/init_os_ctx.c2
-rw-r--r--src/lib/krb5/os/locate_kdc.c11
-rw-r--r--src/util/support/plugins.c271
7 files changed, 279 insertions, 141 deletions
diff --git a/src/include/k5-plugin.h b/src/include/k5-plugin.h
index c7fb1776ca..5bb9be7a00 100644
--- a/src/include/k5-plugin.h
+++ b/src/include/k5-plugin.h
@@ -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));
diff --git a/src/include/stock/osconf.h b/src/include/stock/osconf.h
index 03b2ce651d..26a28054e6 100644
--- a/src/include/stock/osconf.h
+++ b/src/include/stock/osconf.h
@@ -64,7 +64,11 @@
#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
diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c
index 51c31200d3..c6225474a9 100644
--- a/src/lib/kdb/kdb5.c
+++ b/src/lib/kdb/kdb5.c
@@ -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) {
diff --git a/src/lib/kdb/kdb5.h b/src/lib/kdb/kdb5.h
index a522ac686d..9b6d1c70c1 100644
--- a/src/lib/kdb/kdb5.h
+++ b/src/lib/kdb/kdb5.h
@@ -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;
diff --git a/src/lib/krb5/os/init_os_ctx.c b/src/lib/krb5/os/init_os_ctx.c
index e91a05ff1c..8660389402 100644
--- a/src/lib/krb5/os/init_os_ctx.c
+++ b/src/lib/krb5/os/init_os_ctx.c
@@ -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();
diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c
index 83b0066340..979337a35d 100644
--- a/src/lib/krb5/os/locate_kdc.c
+++ b/src/lib/krb5/os/locate_kdc.c
@@ -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;
}
diff --git a/src/util/support/plugins.c b/src/util/support/plugins.c
index a4780f38fa..929d94fa4f 100644
--- a/src/util/support/plugins.c
+++ b/src/util/support/plugins.c
@@ -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;