Exemplo n.º 1
0
static void kim_ui_plugin_context_free (kim_ui_plugin_context *io_context)
{
    if (io_context && *io_context) {
        if ((*io_context)->ftables) {
            krb5int_free_plugin_dir_data ((*io_context)->ftables);
        }
        if (PLUGIN_DIR_OPEN (&(*io_context)->plugins)) {
            krb5int_close_plugin_dirs (&(*io_context)->plugins);
        }
        if ((*io_context)->kcontext) {
            krb5_free_context ((*io_context)->kcontext);
        }
        free (*io_context);
        *io_context = NULL;
    }
}
Exemplo n.º 2
0
Arquivo: kdb5.c Projeto: aosm/Kerberos
static krb5_error_code
kdb_free_library(db_library lib)
{
    krb5_error_code status = 0;
    int     locked = 0;

    if ((status = kdb_lock_list()) != 0) {
	goto clean_n_exit;
    }
    locked = 1;

    lib->reference_cnt--;

    if (lib->reference_cnt == 0) {
	status = lib->vftabl.fini_library();
	if (status) {
	    goto clean_n_exit;
	}

	/* close the library */
        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) {
	    /* first element in the list */
	    lib_list = lib->next;
	} else {
	    lib->prev->next = lib->next;
	}

	if (lib->next) {
	    lib->next->prev = lib->prev;
	}
	free(lib);
    }

  clean_n_exit:
    if (locked) {
	kdb_unlock_list();
    }

    return status;
}
Exemplo n.º 3
0
static krb5_error_code
module_locate_server (krb5_context ctx, const krb5_data *realm,
		      struct addrlist *addrlist,
		      enum locate_service_type svc, int socktype, int family)
{
    struct krb5plugin_service_locate_result *res = NULL;
    krb5_error_code code;
    struct krb5plugin_service_locate_ftable *vtbl = NULL;
    void **ptrs;
    int i;
    struct module_callback_data cbdata = { 0, };

    Tprintf("in module_locate_server\n");
    cbdata.lp = addrlist;
    if (!PLUGIN_DIR_OPEN (&ctx->libkrb5_plugins)) {
        
	code = krb5int_open_plugin_dirs (objdirs, NULL, &ctx->libkrb5_plugins,
					 &ctx->err);
	if (code)
	    return KRB5_PLUGIN_NO_HANDLE;
    }

    code = krb5int_get_plugin_dir_data (&ctx->libkrb5_plugins,
					"service_locator", &ptrs, &ctx->err);
    if (code) {
	Tprintf("error looking up plugin symbols: %s\n",
		krb5_get_error_message(ctx, code));
	return KRB5_PLUGIN_NO_HANDLE;
    }

    for (i = 0; ptrs[i]; i++) {
	void *blob;

	vtbl = ptrs[i];
	Tprintf("element %d is %p\n", i, ptrs[i]);

	/* For now, don't keep the plugin data alive.  For long-lived
	   contexts, it may be desirable to change that later.  */
	code = vtbl->init(ctx, &blob);
	if (code)
	    continue;

	code = vtbl->lookup(blob, svc, realm->data, socktype, family,
			    module_callback, &cbdata);
	vtbl->fini(blob);
	if (code == KRB5_PLUGIN_NO_HANDLE) {
	    /* Module passes, keep going.  */
	    /* XXX */
	    Tprintf("plugin doesn't handle this realm (KRB5_PLUGIN_NO_HANDLE)\n");
	    continue;
	}
	if (code != 0) {
	    /* Module encountered an actual error.  */
	    Tprintf("plugin lookup routine returned error %d: %s\n",
		    code, error_message(code));
	    krb5int_free_plugin_dir_data (ptrs);
	    return code;
	}
	break;
    }
    if (ptrs[i] == NULL) {
	Tprintf("ran off end of plugin list\n");
	krb5int_free_plugin_dir_data (ptrs);
	return KRB5_PLUGIN_NO_HANDLE;
    }
    Tprintf("stopped with plugin #%d, res=%p\n", i, res);

    /* Got something back, yippee.  */
    Tprintf("now have %d addrs in list %p\n", addrlist->naddrs, addrlist);
    print_addrlist(addrlist);
    krb5int_free_plugin_dir_data (ptrs);
    return 0;
}
Exemplo n.º 4
0
Arquivo: kdb5.c Projeto: aosm/Kerberos
static krb5_error_code
kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
{
    krb5_error_code status = 0;
    int     ndx;
    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".
       When it's static, it goes into ".picdata", which is
       read-write.  */
    static const char *const dbpath_names[] = {
	KDB_MODULE_SECTION, "db_module_dir", NULL,
    };
    const char *filebases[2];
    char **profpath = NULL;
    char **path = NULL;

    filebases[0] = lib_name;
    filebases[1] = NULL;

    if (!strcmp(DB2_NAME, lib_name) && (kdb_db2_pol_err_loaded == 0)) {
	initialize_adb_error_table();
	kdb_db2_pol_err_loaded = 1;
    }

    *lib = calloc((size_t) 1, sizeof(**lib));
    if (*lib == NULL) {
	status = ENOMEM;
	goto clean_n_exit;
    }

    status = kdb_init_lib_lock(*lib);
    if (status) {
	goto clean_n_exit;
    }

    strcpy((*lib)->name, lib_name);

    /* Fetch the list of directories specified in the config
       file(s) first.  */
    status = profile_get_values(kcontext->profile, dbpath_names, &profpath);
    if (status != 0 && status != PROF_NO_RELATION)
	goto clean_n_exit;
    ndx = 0;
    if (profpath)
	while (profpath[ndx] != NULL)
	    ndx++;

    path = calloc(ndx + db_dl_n_locations, sizeof (char *));
    if (path == NULL) {
	status = errno;
	goto clean_n_exit;
    }
    if (ndx)
	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;
    }

    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 (vftabl_addrs[0] == NULL) {
	/* No plugins! */
	status = KRB5_KDB_DBTYPE_NOTFOUND;
	krb5_set_error_message (kcontext, status,
				_("Unable to load requested database module '%s': plugin symbol 'kdb_function_table' not found"),
				lib_name);
	goto 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) {
	    kdb_destroy_lib_lock(*lib);
            if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle))) {
                krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle);
            }
	    free(*lib);
	    *lib = NULL;
	}
    }
    return status;
}
Exemplo n.º 5
0
static krb5_error_code
module_locate_server(krb5_context ctx, const krb5_data *realm,
                     struct serverlist *serverlist,
                     enum locate_service_type svc, int socktype)
{
    struct krb5plugin_service_locate_result *res = NULL;
    krb5_error_code code;
    struct krb5plugin_service_locate_ftable *vtbl = NULL;
    void **ptrs;
    char *realmz;               /* NUL-terminated realm */
    int i;
    struct module_callback_data cbdata = { 0, };
    const char *msg;

    Tprintf("in module_locate_server\n");
    cbdata.list = serverlist;
    if (!PLUGIN_DIR_OPEN (&ctx->libkrb5_plugins)) {

        code = krb5int_open_plugin_dirs (objdirs, NULL, &ctx->libkrb5_plugins,
                                         &ctx->err);
        if (code)
            return KRB5_PLUGIN_NO_HANDLE;
    }

    code = krb5int_get_plugin_dir_data (&ctx->libkrb5_plugins,
                                        "service_locator", &ptrs, &ctx->err);
    if (code) {
        Tprintf("error looking up plugin symbols: %s\n",
                (msg = krb5_get_error_message(ctx, code)));
        krb5_free_error_message(ctx, msg);
        return KRB5_PLUGIN_NO_HANDLE;
    }

    if (realm->length >= UINT_MAX) {
        krb5int_free_plugin_dir_data(ptrs);
        return ENOMEM;
    }
    realmz = k5memdup0(realm->data, realm->length, &code);
    if (realmz == NULL) {
        krb5int_free_plugin_dir_data(ptrs);
        return code;
    }
    for (i = 0; ptrs[i]; i++) {
        void *blob;

        vtbl = ptrs[i];
        Tprintf("element %d is %p\n", i, ptrs[i]);

        /* For now, don't keep the plugin data alive.  For long-lived
           contexts, it may be desirable to change that later.  */
        code = vtbl->init(ctx, &blob);
        if (code)
            continue;

        code = vtbl->lookup(blob, svc, realmz,
                            (socktype != 0) ? socktype : SOCK_DGRAM, AF_UNSPEC,
                            module_callback, &cbdata);
        /* Also ask for TCP addresses if we got UDP addresses and want both. */
        if (code == 0 && socktype == 0) {
            code = vtbl->lookup(blob, svc, realmz, SOCK_STREAM, AF_UNSPEC,
                                module_callback, &cbdata);
            if (code == KRB5_PLUGIN_NO_HANDLE)
                code = 0;
        }
        vtbl->fini(blob);
        if (code == KRB5_PLUGIN_NO_HANDLE) {
            /* Module passes, keep going.  */
            /* XXX */
            Tprintf("plugin doesn't handle this realm (KRB5_PLUGIN_NO_HANDLE)\n");
            continue;
        }
        if (code != 0) {
            /* Module encountered an actual error.  */
            Tprintf("plugin lookup routine returned error %d: %s\n",
                    code, error_message(code));
            free(realmz);
            krb5int_free_plugin_dir_data (ptrs);
            return code;
        }
        break;
    }
    if (ptrs[i] == NULL) {
        Tprintf("ran off end of plugin list\n");
        free(realmz);
        krb5int_free_plugin_dir_data (ptrs);
        return KRB5_PLUGIN_NO_HANDLE;
    }
    Tprintf("stopped with plugin #%d, res=%p\n", i, res);

    /* Got something back, yippee.  */
    Tprintf("now have %lu addrs in list %p\n",
            (unsigned long) serverlist->nservers, serverlist);
    free(realmz);
    krb5int_free_plugin_dir_data (ptrs);
    return 0;
}
Exemplo n.º 6
0
krb5_error_code KRB5_CALLCONV
krb5_authdata_context_init(krb5_context kcontext,
                           krb5_authdata_context *pcontext)
{
    int n_modules, n_tables, i, k;
    void **tables = NULL;
    krb5plugin_authdata_client_ftable_v0 *table;
    krb5_authdata_context context = NULL;
    int internal_count = 0;
    struct plugin_dir_handle plugins;
    krb5_error_code code;

    *pcontext = NULL;
    memset(&plugins, 0, sizeof(plugins));

    n_modules = 0;
    for (n_tables = 0; authdata_systems[n_tables] != NULL; n_tables++) {
        n_modules += k5_ad_module_count(authdata_systems[n_tables]);
    }
    internal_count = n_tables;

    if (PLUGIN_DIR_OPEN(&plugins) == 0 &&
        krb5int_open_plugin_dirs(objdirs, NULL,
                                 &plugins,
                                 &kcontext->err) == 0 &&
        krb5int_get_plugin_dir_data(&plugins,
                                    "authdata_client_0",
                                    &tables,
                                    &kcontext->err) == 0 &&
        tables != NULL)
    {
        for (; tables[n_tables - internal_count] != NULL; n_tables++) {
            table = tables[n_tables - internal_count];
            n_modules += k5_ad_module_count(table);
        }
    }

    context = calloc(1, sizeof(*context));
    if (kcontext == NULL) {
        code = ENOMEM;
        goto cleanup;
    }
    context->magic = KV5M_AUTHDATA_CONTEXT;
    context->modules = calloc(n_modules, sizeof(context->modules[0]));
    if (context->modules == NULL) {
        code = ENOMEM;
        goto cleanup;
    }
    context->n_modules = n_modules;

    /* fill in the structure */
    for (i = 0, k = 0, code = 0; i < n_tables - internal_count; i++) {
        code = k5_ad_init_modules(kcontext, context, tables[i], &k);
        if (code != 0)
            goto cleanup;
    }

    for (i = 0; i < internal_count; i++) {
        code = k5_ad_init_modules(kcontext, context, authdata_systems[i], &k);
        if (code != 0)
            goto cleanup;
    }

    context->plugins = plugins;

cleanup:
    if (tables != NULL)
        krb5int_free_plugin_dir_data(tables);

    if (code != 0) {
        krb5int_close_plugin_dirs(&plugins);
        krb5_authdata_context_free(kcontext, context);
    } else {
        /* plugins is owned by context now */
        *pcontext = context;
    }

    return code;
}
Exemplo n.º 7
0
krb5_error_code
load_authdata_plugins(krb5_context context)
{
    struct errinfo err;
    void **authdata_plugins_ftables = NULL;
    struct krb5plugin_authdata_ftable_v0 *ftable = NULL;
    int module_count, i, k;
    init_proc server_init_proc = NULL;

    memset(&err, 0, sizeof(err));

    /* Attempt to load all of the authdata plugins we can find. */
    PLUGIN_DIR_INIT(&authdata_plugins);
    if (PLUGIN_DIR_OPEN(&authdata_plugins) == 0) {
	if (krb5int_open_plugin_dirs(objdirs, NULL,
				     &authdata_plugins, &err) != 0) {
	    return KRB5_PLUGIN_NO_HANDLE;
	}
    }

    /* Get the method tables provided by the loaded plugins. */
    authdata_plugins_ftables = NULL;
    n_authdata_systems = 0;
    if (krb5int_get_plugin_dir_data(&authdata_plugins,
				    "authdata_server_0",
				    &authdata_plugins_ftables, &err) != 0) {
	return KRB5_PLUGIN_NO_HANDLE;
    }

    /* Count the valid modules. */ 
    module_count = sizeof(static_authdata_systems)
		   / sizeof(static_authdata_systems[0]);
    if (authdata_plugins_ftables != NULL) {
		for (i = 0; authdata_plugins_ftables[i] != NULL; i++) {
			ftable = authdata_plugins_ftables[i];
			if ((ftable->authdata_proc != NULL)) {
				module_count++;
			}
		}
    }

    /* Build the complete list of supported authdata options, and
     * leave room for a terminator entry. */
    authdata_systems = calloc((module_count + 1), sizeof(krb5_authdata_systems) );
    if (authdata_systems == NULL) {
		krb5int_free_plugin_dir_data(authdata_plugins_ftables);
		return ENOMEM;
    }

    /* Add the locally-supplied mechanisms to the dynamic list first. */
    for (i = 0, k = 0;
	 i < sizeof(static_authdata_systems) / sizeof(static_authdata_systems[0]);
	 i++) {
			if (static_authdata_systems[i].type == -1)
				break;
			authdata_systems[k] = static_authdata_systems[i];
			/* Try to initialize the authdata system.  If it fails, we'll remove it
			 * from the list of systems we'll be using. */
			server_init_proc = static_authdata_systems[i].init;
			if ((server_init_proc != NULL) &&
				((*server_init_proc)(context, NULL /* &plugin_context */) != 0)) {
				memset(&authdata_systems[k], 0, sizeof(authdata_systems[k]));
				continue;
			}
			k++;
    }

    /* Now add the dynamically-loaded mechanisms to the list. */
    if (authdata_plugins_ftables != NULL) {
		for (i = 0; authdata_plugins_ftables[i] != NULL; i++) {
			ftable = authdata_plugins_ftables[i];
			if ((ftable->authdata_proc == NULL)) {
			continue;
			}
			server_init_proc = ftable->init_proc;
			krb5_error_code initerr;
			if ((server_init_proc != NULL) &&
				((initerr = (*server_init_proc)(context, NULL /* &plugin_context */)) != 0)) {
					const char *emsg;
					emsg = krb5_get_error_message(context, initerr);
					if (emsg) {
						krb5_klog_syslog(LOG_ERR,
							"authdata %s failed to initialize: %s",
							ftable->name, emsg);
						krb5_free_error_message(context, emsg);
					}
					memset(&authdata_systems[k], 0, sizeof(authdata_systems[k]));
		
					continue;
			}
	
			authdata_systems[k].name = ftable->name;
			authdata_systems[k].init = server_init_proc;
			authdata_systems[k].fini = ftable->fini_proc;
			authdata_systems[k].handle_authdata = ftable->authdata_proc;
			k++;
		}
    }
    n_authdata_systems = k;
    /* Add the end-of-list marker. */
    authdata_systems[k].name = "[end]";
	authdata_systems[k].type = -1;
    return 0;
}
Exemplo n.º 8
0
/* Load both v0 and v2 authdata plugins */
krb5_error_code
load_authdata_plugins(krb5_context context)
{
    void **authdata_plugins_ftables_v0 = NULL;
    void **authdata_plugins_ftables_v2 = NULL;
    size_t module_count;
    size_t i, k;
    init_proc server_init_proc = NULL;
    krb5_error_code code;

    /* Attempt to load all of the authdata plugins we can find. */
    PLUGIN_DIR_INIT(&authdata_plugins);
    if (PLUGIN_DIR_OPEN(&authdata_plugins) == 0) {
        if (krb5int_open_plugin_dirs(objdirs, NULL,
                                     &authdata_plugins, &context->err) != 0) {
            return KRB5_PLUGIN_NO_HANDLE;
        }
    }

    /* Get the method tables provided by the loaded plugins. */
    authdata_plugins_ftables_v0 = NULL;
    authdata_plugins_ftables_v2 = NULL;
    n_authdata_systems = 0;

    if (krb5int_get_plugin_dir_data(&authdata_plugins,
                                    "authdata_server_2",
                                    &authdata_plugins_ftables_v2,
                                    &context->err) != 0 ||
        krb5int_get_plugin_dir_data(&authdata_plugins,
                                    "authdata_server_0",
                                    &authdata_plugins_ftables_v0,
                                    &context->err) != 0) {
        code = KRB5_PLUGIN_NO_HANDLE;
        goto cleanup;
    }

    /* Count the valid modules. */
    module_count = 0;

    if (authdata_plugins_ftables_v2 != NULL) {
        struct krb5plugin_authdata_server_ftable_v2 *ftable;

        for (i = 0; authdata_plugins_ftables_v2[i] != NULL; i++) {
            ftable = authdata_plugins_ftables_v2[i];
            if (ftable->authdata_proc != NULL)
                module_count++;
        }
    }

    if (authdata_plugins_ftables_v0 != NULL) {
        struct krb5plugin_authdata_server_ftable_v0 *ftable;

        for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) {
            ftable = authdata_plugins_ftables_v0[i];
            if (ftable->authdata_proc != NULL)
                module_count++;
        }
    }

    module_count += sizeof(static_authdata_systems)
        / sizeof(static_authdata_systems[0]);

    /* Build the complete list of supported authdata options, and
     * leave room for a terminator entry.
     */
    authdata_systems = calloc(module_count + 1, sizeof(krb5_authdata_systems));
    if (authdata_systems == NULL) {
        code = ENOMEM;
        goto cleanup;
    }

    k = 0;

    /*
     * Special case to ensure that handle_request_authdata is
     * first in the list, to make unenc_authdata available to
     * plugins.
     */
    for (i = 0; i < (sizeof(static_authdata_systems) /
                     sizeof(static_authdata_systems[0])); i++) {
        if ((static_authdata_systems[i].flags & AUTHDATA_FLAG_PRE_PLUGIN) == 0)
            continue;
        assert(static_authdata_systems[i].init == NULL);
        authdata_systems[k++] = static_authdata_systems[i];
    }

    /* Add dynamically loaded V2 plugins */
    if (authdata_plugins_ftables_v2 != NULL) {
        struct krb5plugin_authdata_server_ftable_v2 *ftable;

        for (i = 0; authdata_plugins_ftables_v2[i] != NULL; i++) {
            krb5_error_code initerr;
            void *pctx = NULL;

            ftable = authdata_plugins_ftables_v2[i];
            if (ftable->authdata_proc == NULL) {
                continue;
            }
            server_init_proc = ftable->init_proc;
            if ((server_init_proc != NULL) &&
                ((initerr = (*server_init_proc)(context, &pctx)) != 0)) {
                const char *emsg;
                emsg = krb5_get_error_message(context, initerr);
                krb5_klog_syslog(LOG_ERR,
                                 _("authdata %s failed to initialize: %s"),
                                 ftable->name, emsg);
                krb5_free_error_message(context, emsg);
                memset(&authdata_systems[k], 0, sizeof(authdata_systems[k]));

                continue;
            }

            authdata_systems[k].name = ftable->name;
            authdata_systems[k].type = AUTHDATA_SYSTEM_V2;
            authdata_systems[k].init = server_init_proc;
            authdata_systems[k].fini = ftable->fini_proc;
            authdata_systems[k].handle_authdata.v2 = ftable->authdata_proc;
            authdata_systems[k].plugin_context = pctx;
            k++;
        }
    }

    /* Add dynamically loaded V0 plugins */
    if (authdata_plugins_ftables_v0 != NULL) {
        struct krb5plugin_authdata_server_ftable_v0 *ftable;

        for (i = 0; authdata_plugins_ftables_v0[i] != NULL; i++) {
            krb5_error_code initerr;
            void *pctx = NULL;

            ftable = authdata_plugins_ftables_v0[i];
            if (ftable->authdata_proc == NULL) {
                continue;
            }
            server_init_proc = ftable->init_proc;
            if ((server_init_proc != NULL) &&
                ((initerr = (*server_init_proc)(context, &pctx)) != 0)) {
                const char *emsg;
                emsg = krb5_get_error_message(context, initerr);
                krb5_klog_syslog(LOG_ERR,
                                 _("authdata %s failed to initialize: %s"),
                                 ftable->name, emsg);
                krb5_free_error_message(context, emsg);
                memset(&authdata_systems[k], 0, sizeof(authdata_systems[k]));

                continue;
            }

            authdata_systems[k].name = ftable->name;
            authdata_systems[k].type = AUTHDATA_SYSTEM_V0;
            authdata_systems[k].init = server_init_proc;
            authdata_systems[k].fini = ftable->fini_proc;
            authdata_systems[k].handle_authdata.v0 = ftable->authdata_proc;
            authdata_systems[k].plugin_context = pctx;
            k++;
        }
    }

    for (i = 0;
         i < sizeof(static_authdata_systems) / sizeof(static_authdata_systems[0]);
         i++) {
        if (static_authdata_systems[i].flags & AUTHDATA_FLAG_PRE_PLUGIN)
            continue;
        assert(static_authdata_systems[i].init == NULL);
        authdata_systems[k++] = static_authdata_systems[i];
    }

    n_authdata_systems = k;
    /* Add the end-of-list marker. */
    authdata_systems[k].name = "[end]";
    authdata_systems[k].type = AUTHDATA_SYSTEM_UNKNOWN;
    code = 0;

cleanup:
    if (authdata_plugins_ftables_v2 != NULL)
        krb5int_free_plugin_dir_data(authdata_plugins_ftables_v2);
    if (authdata_plugins_ftables_v0 != NULL)
        krb5int_free_plugin_dir_data(authdata_plugins_ftables_v0);

    return code;
}