krb5_error_code krb5_kdc_windc_init(krb5_context context) { struct krb5_plugin *list = NULL, *e; krb5_error_code ret; ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "windc", &list); if(ret != 0 || list == NULL) return 0; for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) { windcft = _krb5_plugin_get_symbol(e); if (windcft->minor_version < KRB5_WINDC_PLUGIN_MINOR) continue; (*windcft->init)(context, &windcctx); break; } _krb5_plugin_free(list); if (e == NULL) { krb5_set_error_message(context, ENOENT, "Did not find any WINDC plugin"); windcft = NULL; return ENOENT; } return 0; }
static void plugin_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, enum locate_service_type type) { struct krb5_plugin *list, *e; krb5_error_code ret; ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "resolve", &list); if(ret != 0 || list == NULL) return; kd->flags |= KD_CONFIG_EXISTS; for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) { krb5plugin_service_locate_ftable *service; void *ctx; service = _krb5_plugin_get_symbol(e); if (service->minor_version != 0) continue; (*service->init)(context, &ctx); ret = (*service->lookup)(ctx, type, kd->realm, 0, 0, add_locate, kd); (*service->fini)(ctx); if (ret) { krb5_set_error_string(context, "Plugin failed to lookup"); break; } } _krb5_plugin_free(list); }
krb5_error_code hdb_create(krb5_context context, HDB **db, const char *filename) { const struct hdb_method *h; const char *residual; krb5_error_code ret; struct krb5_plugin *list = NULL, *e; if(filename == NULL) filename = HDB_DEFAULT_DB; krb5_add_et_list(context, initialize_hdb_error_table_r); h = find_method (filename, &residual); if (h == NULL) { ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "hdb", &list); if(ret == 0 && list != NULL) { for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) { h = _krb5_plugin_get_symbol(e); if (strncmp (filename, h->prefix, strlen(h->prefix)) == 0 && h->interface_version == HDB_INTERFACE_VERSION) { residual = filename + strlen(h->prefix); break; } } if (e == NULL) { h = NULL; _krb5_plugin_free(list); } } } #ifdef HAVE_DLOPEN if (h == NULL) h = find_dynamic_method (context, filename, &residual); #endif if (h == NULL) krb5_errx(context, 1, "No database support for %s", filename); return (*h->create)(context, db, residual); }
static krb5_error_code send_via_plugin(krb5_context context, krb5_krbhst_info *hi, time_t timeout, const krb5_data *send_data, krb5_data *receive) { struct krb5_plugin *list = NULL, *e; krb5_error_code ret; ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, KRB5_PLUGIN_SEND_TO_KDC, &list); if(ret != 0 || list == NULL) return KRB5_PLUGIN_NO_HANDLE; for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) { krb5plugin_send_to_kdc_ftable *service; void *ctx; service = _krb5_plugin_get_symbol(e); if (service->minor_version != 0) continue; (*service->init)(context, &ctx); ret = (*service->send_to_kdc)(context, ctx, hi, timeout, send_data, receive); (*service->fini)(ctx); if (ret == 0) break; if (ret != KRB5_PLUGIN_NO_HANDLE) { krb5_set_error_message(context, ret, N_("Plugin send_to_kdc failed to " "lookup with error: %d", ""), ret); break; } } _krb5_plugin_free(list); return KRB5_PLUGIN_NO_HANDLE; }
static void plugin_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, enum locate_service_type type) { struct krb5_plugin *list = NULL, *e; krb5_error_code ret; ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, KRB5_PLUGIN_LOCATE, &list); if(ret != 0 || list == NULL) return; for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) { krb5plugin_service_locate_ftable *service; void *ctx; service = _krb5_plugin_get_symbol(e); if (service->minor_version != 0) continue; (*service->init)(context, &ctx); ret = (*service->lookup)(ctx, type, kd->realm, 0, 0, add_locate, kd); (*service->fini)(ctx); if (ret && ret != KRB5_PLUGIN_NO_HANDLE) { krb5_set_error_message(context, ret, N_("Locate plugin failed to lookup realm %s: %d", ""), kd->realm, ret); break; } else if (ret == 0) { _krb5_debug(context, 2, "plugin found result for realm %s", kd->realm); kd->flags |= KD_CONFIG_EXISTS; } } _krb5_plugin_free(list); }
/** * Run plugins for the given @module (e.g., "krb5") and @name (e.g., * "kuserok"). Specifically, the @func is invoked once per-plugin with * four arguments: the @context, the plugin symbol value (a pointer to a * struct whose first three fields are the same as struct common_plugin_method), * a context value produced by the plugin's init method, and @userctx. * * @func should unpack arguments for a plugin function and invoke it * with arguments taken from @userctx. @func should save plugin * outputs, if any, in @userctx. * * All loaded and registered plugins are invoked via @func until @func * returns something other than KRB5_PLUGIN_NO_HANDLE. Plugins that * have nothing to do for the given arguments should return * KRB5_PLUGIN_NO_HANDLE. * * Inputs: * * @context A krb5_context * @module Name of module (typically "krb5") * @name Name of pluggable interface (e.g., "kuserok") * @min_version Lowest acceptable plugin minor version number * @flags Flags (none defined at this time) * @userctx Callback data for the callback function @func * @func A callback function, invoked once per-plugin * * Outputs: None, other than the return value and such outputs as are * gathered by @func. */ krb5_error_code _krb5_plugin_run_f(krb5_context context, const char *module, const char *name, int min_version, int flags, void *userctx, krb5_error_code (KRB5_LIB_CALL *func)(krb5_context, const void *, void *, void *)) { heim_string_t m = heim_string_create(module); heim_dict_t dict; void *plug_ctx; struct common_plugin_method *cpm; struct iter_ctx s; struct krb5_plugin *registered_plugins = NULL; struct krb5_plugin *p; /* Get registered plugins */ (void) _krb5_plugin_find(context, SYMBOL, name, ®istered_plugins); HEIMDAL_MUTEX_lock(&plugin_mutex); s.context = context; s.name = name; s.n = heim_string_create(name); s.min_version = min_version; s.result = heim_array_create(); s.func = func; s.userctx = userctx; s.ret = KRB5_PLUGIN_NO_HANDLE; /* Get loaded plugins */ dict = heim_dict_get_value(modules, m); heim_release(m); /* Add loaded plugins to s.result array */ if (dict) heim_dict_iterate_f(dict, &s, search_modules); /* We don't need to hold plugin_mutex during plugin invocation */ HEIMDAL_MUTEX_unlock(&plugin_mutex); /* Invoke registered plugins (old system) */ for (p = registered_plugins; p; p = p->next) { /* * XXX This is the wrong way to handle registered plugins, as we * call init/fini on each invocation! We do this because we * have nowhere in the struct plugin registered list to store * the context allocated by the plugin's init function. (But at * least we do call init/fini!) * * What we should do is adapt the old plugin system to the new * one and change how we register plugins so that we use the new * struct plug to keep track of their context structures, that * way we can init once, invoke many times, then fini. */ cpm = (struct common_plugin_method *)p->symbol; s.ret = cpm->init(context, &plug_ctx); if (s.ret) continue; s.ret = s.func(s.context, p->symbol, plug_ctx, s.userctx); cpm->fini(plug_ctx); if (s.ret != KRB5_PLUGIN_NO_HANDLE) break; } _krb5_plugin_free(registered_plugins); /* Invoke loaded plugins (new system) */ if (s.ret != KRB5_PLUGIN_NO_HANDLE) heim_array_iterate_f(s.result, &s, eval_results); heim_release(s.result); heim_release(s.n); return s.ret; }