diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/k5-plugin.h | 36 | ||||
-rw-r--r-- | src/include/stock/osconf.h | 4 | ||||
-rw-r--r-- | src/lib/kdb/kdb5.c | 94 | ||||
-rw-r--r-- | src/lib/kdb/kdb5.h | 2 | ||||
-rw-r--r-- | src/lib/krb5/os/init_os_ctx.c | 2 | ||||
-rw-r--r-- | src/lib/krb5/os/locate_kdc.c | 11 | ||||
-rw-r--r-- | src/util/support/plugins.c | 271 |
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; |