Пример #1
0
/* 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;
}
Пример #2
0
long KRB5_CALLCONV
krb5int_get_plugin_dir_func (struct plugin_dir_handle *dirhandle,
			     const char *symname,
			     void (***ptrs)(void),
			     struct errinfo *ep)
{
    long err = 0;
    void (**p)() = NULL;
    int count = 0;
    
    /* XXX Do we need to add a leading "_" to the symbol name on any
        modern platforms?  */
    
    Tprintf("get_plugin_data_sym(%s)\n", symname);
    
    if (!err) {
        p = calloc (1, sizeof (*p)); /* calloc initializes to NULL */
        if (p == NULL) { err = errno; }
    }
    
    if (!err && (dirhandle != NULL) && (dirhandle->files != NULL)) {
        int i = 0;
        
        for (i = 0; !err && (dirhandle->files[i] != NULL); i++) {
            void (*sym)() = NULL;
            
            if (krb5int_get_plugin_func (dirhandle->files[i], symname, &sym, ep) == 0) {
                void (**newp)() = NULL;

                count++;
                newp = realloc (p, ((count + 1) * sizeof (*p))); /* +1 for NULL */
                if (newp == NULL) { 
                    err = errno; 
                } else {
                    p = newp;
                    p[count - 1] = sym;
                    p[count] = NULL;
                }
            }
        }
    }
    
    if (!err) {
        *ptrs = p;
        p = NULL; /* ptrs takes ownership */
    }
    
    if (p != NULL) { free (p); }
    
    return err;
}
Пример #3
0
/* 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;
}