/* If map is for a dynamic module which hasn't been loaded yet, attempt to load * it. Only try to load a module once. */ static void load_if_needed(krb5_context context, struct plugin_mapping *map, const char *iname) { char *symname = NULL; struct plugin_file_handle *handle = NULL; void (*initvt_fn)(); if (map->module != NULL || map->dyn_path == NULL) return; if (asprintf(&symname, "%s_%s_initvt", iname, map->modname) < 0) return; if (krb5int_open_plugin(map->dyn_path, &handle, &context->err)) goto err; if (krb5int_get_plugin_func(handle, symname, &initvt_fn, &context->err)) goto err; free(symname); map->dyn_handle = handle; map->module = (krb5_plugin_initvt_fn)initvt_fn; return; err: /* Clean up, and also null out map->dyn_path so we don't try again. */ if (handle != NULL) krb5int_close_plugin(handle); free(symname); free(map->dyn_path); map->dyn_path = NULL; }
void KRB5_CALLCONV profile_abandon(profile_t profile) { prf_file_t p, next; errcode_t err; if (!profile || profile->magic != PROF_MAGIC_PROFILE) return; if (profile->vt) { if (profile->vt->cleanup) profile->vt->cleanup(profile->cbdata); if (profile->lib_handle) { /* Decrement the refcount on the handle and maybe free it. */ err = k5_mutex_lock(&profile->lib_handle->lock); if (!err && --profile->lib_handle->refcount == 0) { krb5int_close_plugin(profile->lib_handle->plugin_handle); k5_mutex_unlock(&profile->lib_handle->lock); k5_mutex_destroy(&profile->lib_handle->lock); free(profile->lib_handle); } else if (!err) k5_mutex_unlock(&profile->lib_handle->lock); } free(profile->vt); } else { for (p = profile->first_file; p; p = next) { next = p->next; profile_free_file(p); } } profile->magic = 0; free(profile); }
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); } }
/* Release the memory associated with the mapping list entry map. */ static void free_plugin_mapping(struct plugin_mapping *map) { if (map == NULL) return; free(map->modname); free(map->dyn_path); if (map->dyn_handle != NULL) krb5int_close_plugin(map->dyn_handle); free(map); }
void KRB5_CALLCONV krb5int_close_plugin_dirs (struct plugin_dir_handle *dirhandle) { if (dirhandle->files != NULL) { int i; for (i = 0; dirhandle->files[i] != NULL; i++) { krb5int_close_plugin (dirhandle->files[i]); } free (dirhandle->files); dirhandle->files = NULL; } }
long KRB5_CALLCONV krb5int_open_plugin_dirs (const char * const *dirnames, const char * const *filebases, struct plugin_dir_handle *dirhandle, struct errinfo *ep) { long err = 0; struct plugin_file_handle **h = NULL; int count = 0; char **filenames = NULL; int i; if (!err) { err = krb5int_plugin_file_handle_array_init (&h); } if (!err && (filebases != NULL)) { err = krb5int_get_plugin_filenames (filebases, &filenames); } 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 { /*LINTED*/ 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); } } } else { /* load all plugins in each directory */ #ifndef _WIN32 DIR *dir = opendir (dirnames[i]); while (dir != NULL && !err) { struct dirent *d = NULL; char *filepath = NULL; struct plugin_file_handle *handle = NULL; int len; d = readdir (dir); if (d == NULL) { break; } if ((strcmp (d->d_name, ".") == 0) || (strcmp (d->d_name, "..") == 0)) { continue; } /* Solaris Kerberos: Only open files with a .so extension */ len = NAMELEN (d); if (len < 3 || strcmp(".so", d->d_name + len - 3 ) != 0) continue; if (!err) { filepath = malloc (dirnamelen + len + 1); /* NULL */ if (filepath == NULL) { err = errno; } else { /*LINTED*/ 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); } #else /* Until a Windows implementation of this code is implemented */ err = ENOENT; #endif /* _WIN32 */ } } if (err == ENOENT) { err = 0; /* ran out of plugins -- do nothing */ } if (!err) { dirhandle->files = h; h = NULL; /* dirhandle->files takes ownership */ } if (filenames != NULL) { krb5int_free_plugin_filenames (filenames); } if (h != NULL) { krb5int_plugin_file_handle_array_free (h); } return err; }
/* Load a dynamic profile module as specified by modspec and create a vtable * profile for it in *ret_profile. */ static errcode_t init_load_module(const char *modspec, profile_t *ret_profile) { char *modpath = NULL, *residual = NULL; struct errinfo einfo = { 0 }; prf_lib_handle_t lib_handle = NULL; struct plugin_file_handle *plhandle = NULL; void *cbdata = NULL, (*fptr)(); int have_lock = 0, have_cbdata = 0; struct profile_vtable vtable = { 1 }; /* Set minor_ver to 1, rest null. */ errcode_t err; profile_module_init_fn initfn; err = parse_modspec(modspec, &modpath, &residual); if (err) goto cleanup; /* Allocate a reference-counted library handle container. */ lib_handle = malloc(sizeof(*lib_handle)); if (lib_handle == NULL) goto cleanup; err = k5_mutex_init(&lib_handle->lock); if (err) goto cleanup; have_lock = 1; /* Open the module and get its initializer. */ err = krb5int_open_plugin(modpath, &plhandle, &einfo); if (err) goto cleanup; err = krb5int_get_plugin_func(plhandle, "profile_module_init", &fptr, &einfo); if (err == ENOENT) err = PROF_MODULE_INVALID; if (err) goto cleanup; /* Get the profile vtable and callback data pointer. */ initfn = (profile_module_init_fn)fptr; err = (*initfn)(residual, &vtable, &cbdata); if (err) goto cleanup; have_cbdata = 1; /* Create a vtable profile with the information obtained. */ lib_handle->plugin_handle = plhandle; lib_handle->refcount = 1; err = init_module(&vtable, cbdata, lib_handle, ret_profile); cleanup: free(modpath); free(residual); k5_clear_error(&einfo); if (err) { if (have_cbdata && vtable.cleanup) vtable.cleanup(cbdata); if (have_lock) k5_mutex_destroy(&lib_handle->lock); free(lib_handle); if (plhandle) krb5int_close_plugin(plhandle); } return err; }
long KRB5_CALLCONV krb5int_open_plugin_dirs (const char * const *dirnames, const char * const *filebases, struct plugin_dir_handle *dirhandle, struct errinfo *ep) { long err = 0; struct plugin_file_handle **h = NULL; size_t count = 0; char **filenames = NULL; int i; if (!err) { err = krb5int_plugin_file_handle_array_init (&h); } if (!err && (filebases != NULL)) { err = krb5int_get_plugin_filenames (filebases, &filenames); } for (i = 0; !err && dirnames[i] != NULL; i++) { 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) { if (asprintf(&filepath, "%s/%s", dirnames[i], filenames[j]) < 0) { filepath = NULL; err = ENOMEM; } } 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 */ } free(filepath); if (handle != NULL) { krb5int_close_plugin (handle); } } } else { /* load all plugins in each directory */ DIR *dir = opendir (dirnames[i]); while (dir != NULL && !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); if (asprintf(&filepath, "%s/%*s", dirnames[i], len, d->d_name) < 0) { filepath = NULL; err = ENOMEM; } } 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 */ } } free(filepath); if (handle != NULL) { krb5int_close_plugin (handle); } } if (dir != NULL) { closedir (dir); } } } if (err == ENOENT) { err = 0; /* ran out of plugins -- do nothing */ } if (!err) { dirhandle->files = h; h = NULL; /* dirhandle->files takes ownership */ } if (filenames != NULL) { krb5int_free_plugin_filenames (filenames); } if (h != NULL) { krb5int_plugin_file_handle_array_free (h); } return err; }