From cd1d7f4be7d31388ab79c797acaf6d7730113112 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 5 Aug 2009 11:25:50 +1000 Subject: s4:heimdal: import lorikeet-heimdal-200908050050 (commit 8714779fa7376fd9f7761587639e68b48afc8c9c) This also adds a new hdb-glue.c file, to cope with Heimdal's uncondtional enabling of SQLITE. (Very reasonable, but not required for Samba4's use). Andrew Bartlett --- source4/heimdal/lib/krb5/plugin.c | 200 ++++++++++++++++++++++---------------- 1 file changed, 117 insertions(+), 83 deletions(-) (limited to 'source4/heimdal/lib/krb5/plugin.c') diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index 844cb7ab88..027f2a72a7 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -40,19 +40,28 @@ struct krb5_plugin { void *symbol; - void *dsohandle; struct krb5_plugin *next; }; struct plugin { - enum krb5_plugin_type type; - void *name; - void *symbol; + enum { DSO, SYMBOL } type; + union { + struct { + char *path; + void *dsohandle; + } dso; + struct { + enum krb5_plugin_type type; + char *name; + char *symbol; + } symbol; + } u; struct plugin *next; }; static HEIMDAL_MUTEX plugin_mutex = HEIMDAL_MUTEX_INITIALIZER; static struct plugin *registered = NULL; +static int plugins_needs_scan = 1; static const char *sysplugin_dirs[] = { LIBDIR "/plugin/krb5", @@ -85,15 +94,14 @@ _krb5_plugin_get_next(struct krb5_plugin *p) #ifdef HAVE_DLOPEN static krb5_error_code -loadlib(krb5_context context, - enum krb5_plugin_type type, - const char *name, - const char *lib, - struct krb5_plugin **e) +loadlib(krb5_context context, char *path) { - *e = calloc(1, sizeof(**e)); - if (*e == NULL) { + struct plugin *e; + + e = calloc(1, sizeof(*e)); + if (e == NULL) { krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); + free(path); return ENOMEM; } @@ -103,24 +111,13 @@ loadlib(krb5_context context, #ifndef RTLD_LOCAL #define RTLD_LOCAL 0 #endif + e->type = DSO; + /* ignore error from dlopen, and just keep it as negative cache entry */ + e->u.dso.dsohandle = dlopen(path, RTLD_LOCAL|RTLD_LAZY); + e->u.dso.path = path; - (*e)->dsohandle = dlopen(lib, RTLD_LOCAL|RTLD_LAZY); - if ((*e)->dsohandle == NULL) { - free(*e); - *e = NULL; - krb5_set_error_message(context, ENOMEM, "Failed to load %s: %s", - lib, dlerror()); - return ENOMEM; - } - - /* dlsym doesn't care about the type */ - (*e)->symbol = dlsym((*e)->dsohandle, name); - if ((*e)->symbol == NULL) { - dlclose((*e)->dsohandle); - free(*e); - krb5_clear_error_message(context); - return ENOMEM; - } + e->next = registered; + registered = e; return 0; } @@ -146,26 +143,35 @@ krb5_plugin_register(krb5_context context, { struct plugin *e; + HEIMDAL_MUTEX_lock(&plugin_mutex); + /* check for duplicates */ - for (e = registered; e != NULL; e = e->next) - if (e->type == type && strcmp(e->name,name)== 0 && e->symbol == symbol) + for (e = registered; e != NULL; e = e->next) { + if (e->type == SYMBOL && + strcmp(e->u.symbol.name, name) == 0 && + e->u.symbol.type == type && e->u.symbol.symbol == symbol) { + HEIMDAL_MUTEX_unlock(&plugin_mutex); return 0; + } + } e = calloc(1, sizeof(*e)); if (e == NULL) { + HEIMDAL_MUTEX_unlock(&plugin_mutex); krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } - e->type = type; - e->name = strdup(name); - if (e->name == NULL) { + e->type = SYMBOL; + e->u.symbol.type = type; + e->u.symbol.name = strdup(name); + if (e->u.symbol.name == NULL) { + HEIMDAL_MUTEX_unlock(&plugin_mutex); free(e); krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } - e->symbol = symbol; + e->u.symbol.symbol = symbol; - HEIMDAL_MUTEX_lock(&plugin_mutex); e->next = registered; registered = e; HEIMDAL_MUTEX_unlock(&plugin_mutex); @@ -173,41 +179,19 @@ krb5_plugin_register(krb5_context context, return 0; } -krb5_error_code -_krb5_plugin_find(krb5_context context, - enum krb5_plugin_type type, - const char *name, - struct krb5_plugin **list) +static krb5_error_code +load_plugins(krb5_context context) { - struct krb5_plugin *e; - struct plugin *p; + struct plugin *e; krb5_error_code ret; char **dirs = NULL, **di; struct dirent *entry; char *path; DIR *d = NULL; - *list = NULL; - - HEIMDAL_MUTEX_lock(&plugin_mutex); - - for (p = registered; p != NULL; p = p->next) { - if (p->type != type || strcmp(p->name, name) != 0) - continue; - - e = calloc(1, sizeof(*e)); - if (e == NULL) { - HEIMDAL_MUTEX_unlock(&plugin_mutex); - ret = ENOMEM; - krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; - } - e->symbol = p->symbol; - e->dsohandle = NULL; - e->next = *list; - *list = e; - } - HEIMDAL_MUTEX_unlock(&plugin_mutex); + if (!plugins_needs_scan) + return 0; + plugins_needs_scan = 0; #ifdef HAVE_DLOPEN @@ -244,21 +228,83 @@ _krb5_plugin_find(krb5_context context, if (path == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, "malloc: out of memory"); - goto out; + return ret; + } + + /* check if already tried */ + for (e = registered; e != NULL; e = e->next) + if (e->type == DSO && strcmp(e->u.dso.path, path) == 0) + break; + if (e) { + free(path); + } else { + loadlib(context, path); /* store or frees path */ } - ret = loadlib(context, type, name, path, &e); - free(path); - if (ret) - continue; - - e->next = *list; - *list = e; } closedir(d); } if (dirs != rk_UNCONST(sysplugin_dirs)) krb5_config_free_strings(dirs); #endif /* HAVE_DLOPEN */ + return 0; +} + +static krb5_error_code +add_symbol(krb5_context context, struct krb5_plugin **list, void *symbol) +{ + struct krb5_plugin *e; + + e = calloc(1, sizeof(*e)); + if (e == NULL) { + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); + return ENOMEM; + } + e->symbol = symbol; + e->next = *list; + *list = e; + return 0; +} + +krb5_error_code +_krb5_plugin_find(krb5_context context, + enum krb5_plugin_type type, + const char *name, + struct krb5_plugin **list) +{ + struct plugin *e; + krb5_error_code ret; + + *list = NULL; + + HEIMDAL_MUTEX_lock(&plugin_mutex); + + load_plugins(context); + + for (ret = 0, e = registered; e != NULL; e = e->next) { + switch(e->type) { + case DSO: { + void *sym; + if (e->u.dso.dsohandle == NULL) + continue; + sym = dlsym(e->u.dso.dsohandle, name); + if (sym) + ret = add_symbol(context, list, sym); + break; + } + case SYMBOL: + if (strcmp(e->u.symbol.name, name) == 0 && e->u.symbol.type == type) + ret = add_symbol(context, list, e->u.symbol.symbol); + break; + } + if (ret) { + _krb5_plugin_free(*list); + *list = NULL; + } + } + + HEIMDAL_MUTEX_unlock(&plugin_mutex); + if (ret) + return ret; if (*list == NULL) { krb5_set_error_message(context, ENOENT, "Did not find a plugin for %s", name); @@ -266,16 +312,6 @@ _krb5_plugin_find(krb5_context context, } return 0; - -out: - if (dirs != rk_UNCONST(sysplugin_dirs)) - krb5_config_free_strings(dirs); - if (d) - closedir(d); - _krb5_plugin_free(*list); - *list = NULL; - - return ret; } void @@ -284,8 +320,6 @@ _krb5_plugin_free(struct krb5_plugin *list) struct krb5_plugin *next; while (list) { next = list->next; - if (list->dsohandle) - dlclose(list->dsohandle); free(list); list = next; } -- cgit