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; } }
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; }
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; }
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; }
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; }
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; }
/* 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; }