static krb5_error_code kcm_send_request(krb5_context context, krb5_storage *request, krb5_data *response_data) { static heim_base_once_t init_once = HEIM_BASE_ONCE_INIT; krb5_error_code ret = 0; krb5_data request_data; heim_base_once_f(&init_once, NULL, kcm_init_ipc); if (kcm_ipc == NULL) { krb5_set_error_message(context, ENOENT, "Failed to open kcm init"); return ENOENT; } ret = krb5_storage_to_data(request, &request_data); if (ret) { krb5_clear_error_message(context); return KRB5_CC_NOMEM; } ret = heim_ipc_call(kcm_ipc, &request_data, response_data, NULL); krb5_data_free(&request_data); if (ret) { krb5_clear_error_message(context); ret = KRB5_CC_NOSUPP; } return ret; }
krb5_error_code _gsskrb5_init (krb5_context *context) { static heim_base_once_t once; krb5_error_code ret = 0; heim_base_once_f(&once, NULL, once_func); *context = HEIMDAL_getspecific(context_key); if (*context == NULL) { ret = krb5_init_context(context); if (ret == 0) { HEIMDAL_setspecific(context_key, *context, ret); if (ret) { krb5_free_context(*context); *context = NULL; } } } else { krb5_reload_config(*context, 0, NULL); } return ret; }
/** heim_db_register * @brief Registers a DB type for use with heim_db_create(). * * @param dbtype Name of DB type * @param data Private data argument to the dbtype's openf method * @param plugin Structure with DB type methods (function pointers) * * Backends that provide begin/commit/rollback methods must provide ACID * semantics. * * The registered DB type will have ACID semantics for backends that do * not provide begin/commit/rollback methods but do provide lock/unlock * and rdjournal/wrjournal methods (using a replay log journalling * scheme). * * If the registered DB type does not natively provide read vs. write * transaction isolation but does provide a lock method then the DB will * provide read/write transaction isolation. * * @return ENOMEM on failure, else 0. * * @addtogroup heimbase */ int heim_db_register(const char *dbtype, void *data, struct heim_db_type *plugin) { heim_dict_t plugins; heim_string_t s; db_plugin plug, plug2; int ret = 0; if ((plugin->beginf != NULL && plugin->commitf == NULL) || (plugin->beginf != NULL && plugin->rollbackf == NULL) || (plugin->lockf != NULL && plugin->unlockf == NULL) || plugin->copyf == NULL) heim_abort("Invalid DB plugin; make sure methods are paired"); /* Initialize */ plugins = heim_dict_create(11); if (plugins == NULL) return ENOMEM; heim_base_once_f(&db_plugin_init_once, plugins, db_init_plugins_once); heim_release(plugins); heim_assert(db_plugins != NULL, "heim_db plugin table initialized"); s = heim_string_create(dbtype); if (s == NULL) return ENOMEM; plug = heim_alloc(sizeof (*plug), "db_plug", plugin_dealloc); if (plug == NULL) { heim_release(s); return ENOMEM; } plug->name = heim_retain(s); plug->openf = plugin->openf; plug->clonef = plugin->clonef; plug->closef = plugin->closef; plug->lockf = plugin->lockf; plug->unlockf = plugin->unlockf; plug->syncf = plugin->syncf; plug->beginf = plugin->beginf; plug->commitf = plugin->commitf; plug->rollbackf = plugin->rollbackf; plug->copyf = plugin->copyf; plug->setf = plugin->setf; plug->delf = plugin->delf; plug->iterf = plugin->iterf; plug->data = data; HEIMDAL_MUTEX_lock(&db_type_mutex); plug2 = heim_dict_get_value(db_plugins, s); if (plug2 == NULL) ret = heim_dict_set_value(db_plugins, s, plug); HEIMDAL_MUTEX_unlock(&db_type_mutex); heim_release(plug); heim_release(s); return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_init_context_flags(unsigned int flags, krb5_context *context) { static heim_base_once_t init_context = HEIM_BASE_ONCE_INIT; krb5_context p; krb5_error_code ret; char **files = NULL; *context = NULL; p = calloc(1, sizeof(*p)); if (!p) return ENOMEM; p->mutex = malloc(sizeof(HEIMDAL_MUTEX)); if (p->mutex == NULL) { free(p); return ENOMEM; } HEIMDAL_MUTEX_init(p->mutex); HEIMDAL_MUTEX_lock(&homedir_mutex); if (allow_homedir) p->flags |= KRB5_CTX_F_HOMEDIR_ACCESS; HEIMDAL_MUTEX_unlock(&homedir_mutex); if ((flags & KRB5_CONTEXT_FLAG_NO_CONFIG) == 0) { ret = krb5_get_default_config_files(&files); if (ret) goto out; } ret = krb5_set_config_files(p, files); krb5_free_config_files(files); if (ret) goto out; heim_base_once_f(&init_context, p, init_context_once); /* init error tables */ krb5_init_ets(p); cc_ops_register(p); kt_ops_register(p); #ifdef PKINIT ret = hx509_context_init(&p->hx509ctx); if (ret) goto out; #endif if (rk_SOCK_INIT()) p->flags |= KRB5_CTX_F_SOCKETS_INITIALIZED; out: if (ret) { krb5_free_context(p); p = NULL; } *context = p; return ret; }
heim_object_t heim_json_create_with_bytes(const void *data, size_t length, size_t max_depth, heim_json_flags_t flags, heim_error_t *error) { struct parse_ctx ctx; heim_object_t o; heim_base_once_f(&heim_json_once, NULL, json_init_once); ctx.lineno = 1; ctx.p = data; ctx.pstart = data; ctx.pend = ((uint8_t *)data) + length; ctx.error = NULL; ctx.flags = flags; ctx.depth = max_depth; o = parse_value(&ctx); if (o == NULL && error) { *error = ctx.error; } else if (ctx.error) { heim_release(ctx.error); } return o; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_init_context(krb5_context *context) { static heim_base_once_t init_context = HEIM_BASE_ONCE_INIT; krb5_context p; krb5_error_code ret; char **files; *context = NULL; p = calloc(1, sizeof(*p)); if(!p) return ENOMEM; p->mutex = malloc(sizeof(HEIMDAL_MUTEX)); if (p->mutex == NULL) { free(p); return ENOMEM; } HEIMDAL_MUTEX_init(p->mutex); p->flags |= KRB5_CTX_F_HOMEDIR_ACCESS; ret = krb5_get_default_config_files(&files); if(ret) goto out; ret = krb5_set_config_files(p, files); krb5_free_config_files(files); if(ret) goto out; /* done enough to load plugins */ heim_base_once_f(&init_context, p, init_context_once); /* init error tables */ krb5_init_ets(p); cc_ops_register(p); kt_ops_register(p); #ifdef PKINIT ret = hx509_context_init(&p->hx509ctx); if (ret) goto out; #endif if (rk_SOCK_INIT()) p->flags |= KRB5_CTX_F_SOCKETS_INITIALIZED; out: if(ret) { krb5_free_context(p); p = NULL; } *context = p; return ret; }
static const hc_EVP_CIPHER * get_EVP_CIPHER(heim_base_once_t *once, hc_EVP_CIPHER *hc_memoize, const hc_EVP_CIPHER **hc_memoizep, const hc_EVP_CIPHER *fallback, unsigned long flags, int nid) { struct once_init_cipher_ctx arg; arg.flags = flags; arg.hc_memoizep = hc_memoizep; arg.hc_memoize = hc_memoize; arg.fallback = fallback; arg.nid = nid; heim_base_once_f(once, &arg, get_EVP_CIPHER_once_cb); return *hc_memoizep; /* May be NULL */ }
static int heim_base2json(heim_object_t obj, void *ctx, heim_json_flags_t flags, void (*out)(void *, const char *)) { struct twojson j; if (flags & HEIM_JSON_F_STRICT_STRINGS) return ENOTSUP; /* Sorry, not yet! */ heim_base_once_f(&heim_json_once, NULL, json_init_once); j.indent = 0; j.ctx = ctx; j.out = out; j.flags = flags; j.ret = 0; j.first = 1; return base2json(obj, &j); }
heim_string_t __heim_string_constant(const char *_str) { static HEIMDAL_MUTEX mutex = HEIMDAL_MUTEX_INITIALIZER; static heim_base_once_t once; static heim_dict_t dict = NULL; heim_string_t s, s2; heim_base_once_f(&once, &dict, init_string); s = heim_string_create(_str); HEIMDAL_MUTEX_lock(&mutex); s2 = heim_dict_get_value(dict, s); if (s2) { heim_release(s); s = s2; } else { _heim_make_permanent(s); heim_dict_set_value(dict, s, s); } HEIMDAL_MUTEX_unlock(&mutex); return s; }
static krb5_error_code an2ln_def_plug_an2ln(void *plug_ctx, krb5_context context, const char *rule, krb5_const_principal aname, set_result_f set_res_f, void *set_res_ctx) { krb5_error_code ret; const char *an2ln_db_fname; heim_db_t dbh = NULL; heim_dict_t db_options; heim_data_t k, v; heim_error_t error; char *unparsed = NULL; char *value = NULL; _krb5_load_db_plugins(context); heim_base_once_f(&sorted_text_db_init_once, NULL, sorted_text_db_init_f); if (strncmp(rule, "DB:", strlen("DB:") != 0)) return KRB5_PLUGIN_NO_HANDLE; an2ln_db_fname = &rule[strlen("DB:")]; if (!*an2ln_db_fname) return KRB5_PLUGIN_NO_HANDLE; ret = krb5_unparse_name(context, aname, &unparsed); if (ret) return ret; db_options = heim_dict_create(11); if (db_options != NULL) heim_dict_set_value(db_options, HSTR("read-only"), heim_number_create(1)); dbh = heim_db_create(NULL, an2ln_db_fname, db_options, &error); if (dbh == NULL) { krb5_set_error_message(context, heim_error_get_code(error), N_("Couldn't open aname2lname-text-db", "")); ret = KRB5_PLUGIN_NO_HANDLE; goto cleanup; } /* Binary search; file should be sorted (in C locale) */ k = heim_data_ref_create(unparsed, strlen(unparsed), NULL); if (k == NULL) return krb5_enomem(context); v = heim_db_copy_value(dbh, NULL, k, &error); heim_release(k); if (v == NULL && error != NULL) { krb5_set_error_message(context, heim_error_get_code(error), N_("Lookup in aname2lname-text-db failed", "")); ret = heim_error_get_code(error); goto cleanup; } else if (v == NULL) { ret = KRB5_PLUGIN_NO_HANDLE; goto cleanup; } else { /* found */ if (heim_data_get_length(v) == 0) { krb5_set_error_message(context, ret, N_("Principal mapped to empty username", "")); ret = KRB5_NO_LOCALNAME; goto cleanup; } ret = set_res_f(set_res_ctx, heim_data_get_ptr(v)); heim_release(v); } cleanup: heim_release(dbh); free(unparsed); free(value); return ret; }
/** * Map a principal name to a local username. * * Returns 0 on success, KRB5_NO_LOCALNAME if no mapping was found, or * some Kerberos or system error. * * Inputs: * * @param context A krb5_context * @param aname A principal name * @param lnsize The size of the buffer into which the username will be written * @param lname The buffer into which the username will be written * * @ingroup krb5_support */ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_aname_to_localname(krb5_context context, krb5_const_principal aname, size_t lnsize, char *lname) { static heim_base_once_t reg_def_plugins = HEIM_BASE_ONCE_INIT; krb5_error_code ret; size_t i; char **rules = NULL; char *rule; if (lnsize) lname[0] = '\0'; heim_base_once_f(®_def_plugins, context, reg_def_plugins_once); /* Try MIT's auth_to_local_names config first */ ret = an2ln_local_names(context, aname, lnsize, lname); if (ret != KRB5_PLUGIN_NO_HANDLE) return ret; rules = krb5_config_get_strings(context, NULL, "realms", aname->realm, "auth_to_local", NULL); if (!rules) { /* Heimdal's default rule */ ret = an2ln_default(context, "HEIMDAL_DEFAULT", aname, lnsize, lname); if (ret == KRB5_PLUGIN_NO_HANDLE) return KRB5_NO_LOCALNAME; return ret; } /* * MIT rules. * * Note that RULEs and DBs only have white-list functionality, * thus RULEs and DBs that we don't understand we simply ignore. * * This means that plugins that implement black-lists are * dangerous: if a black-list plugin isn't found, the black-list * won't be enforced. But black-lists are dangerous anyways. */ for (ret = KRB5_PLUGIN_NO_HANDLE, i = 0; rules[i]; i++) { rule = rules[i]; /* Try NONE, DEFAULT, and HEIMDAL_DEFAULT rules */ ret = an2ln_default(context, rule, aname, lnsize, lname); if (ret == KRB5_PLUGIN_NO_HANDLE) /* Try DB, RULE, ... plugins */ ret = an2ln_plugin(context, rule, aname, lnsize, lname); if (ret == 0 && lnsize && !lname[0]) continue; /* Success but no lname?! lies! */ else if (ret != KRB5_PLUGIN_NO_HANDLE) break; } if (ret == KRB5_PLUGIN_NO_HANDLE) { if (lnsize) lname[0] = '\0'; ret = KRB5_NO_LOCALNAME; } krb5_config_free_strings(rules); return ret; }
void _krb5_load_db_plugins(krb5_context context) { heim_base_once_f(&db_plugins_once, context, db_plugins_init); }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_init_context(krb5_context *context) { static heim_base_once_t init_context = HEIM_BASE_ONCE_INIT; krb5_context p; krb5_error_code ret; char **files; uint8_t rnd; *context = NULL; /** * krb5_init_context() will get one random byte to make sure our * random is alive. Assumption is that once the non blocking * source allows us to pull bytes, its all seeded and allows us to * pull more bytes. * * Most Kerberos users calls krb5_init_context(), so this is * useful point where we can do the checking. */ ret = krb5_generate_random(&rnd, sizeof(rnd)); if (ret) return ret; p = calloc(1, sizeof(*p)); if(!p) return ENOMEM; p->mutex = malloc(sizeof(HEIMDAL_MUTEX)); if (p->mutex == NULL) { free(p); return ENOMEM; } HEIMDAL_MUTEX_init(p->mutex); p->flags |= KRB5_CTX_F_HOMEDIR_ACCESS; ret = krb5_get_default_config_files(&files); if(ret) goto out; ret = krb5_set_config_files(p, files); krb5_free_config_files(files); if(ret) goto out; /* done enough to load plugins */ heim_base_once_f(&init_context, p, init_context_once); /* init error tables */ krb5_init_ets(p); cc_ops_register(p); kt_ops_register(p); #ifdef PKINIT ret = hx509_context_init(&p->hx509ctx); if (ret) goto out; #endif if (rk_SOCK_INIT()) p->flags |= KRB5_CTX_F_SOCKETS_INITIALIZED; out: if(ret) { krb5_free_context(p); p = NULL; } *context = p; return ret; }
KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL _krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser, krb5_boolean an2ln_ok) { static heim_base_once_t reg_def_plugins = HEIM_BASE_ONCE_INIT; krb5_error_code ret; struct plctx ctx; char **rules; /* * XXX we should have a struct with a krb5_context field and a * krb5_error_code fied and pass the address of that as the ctx * argument of heim_base_once_f(). For now we use a static to * communicate failures. Actually, we ignore failures anyways, * since we can't return them. */ heim_base_once_f(®_def_plugins, context, reg_def_plugins_once); ctx.flags = 0; ctx.luser = luser; ctx.principal = principal; ctx.result = FALSE; ctx.k5login_dir = krb5_config_get_string(context, NULL, "libdefaults", "k5login_directory", NULL); if (an2ln_ok) ctx.flags |= KUSEROK_ANAME_TO_LNAME_OK; if (krb5_config_get_bool_default(context, NULL, FALSE, "libdefaults", "k5login_authoritative", NULL)) ctx.flags |= KUSEROK_K5LOGIN_IS_AUTHORITATIVE; if ((ctx.flags & KUSEROK_K5LOGIN_IS_AUTHORITATIVE) && plugin_reg_ret) return plugin_reg_ret; /* fail safe */ rules = krb5_config_get_strings(context, NULL, "libdefaults", "kuserok", NULL); if (rules == NULL) { /* Default: check ~/.k5login */ ctx.rule = "USER-K5LOGIN"; ret = plcallback(context, &kuserok_user_k5login_plug, NULL, &ctx); if (ret == 0) goto out; ctx.rule = "SIMPLE"; ret = plcallback(context, &kuserok_simple_plug, NULL, &ctx); if (ret == 0) goto out; ctx.result = FALSE; } else { size_t n; for (n = 0; rules[n]; n++) { ctx.rule = rules[n]; ret = _krb5_plugin_run_f(context, "krb5", KRB5_PLUGIN_KUSEROK, KRB5_PLUGIN_KUSEROK_VERSION_0, 0, &ctx, plcallback); if (ret != KRB5_PLUGIN_NO_HANDLE) goto out; } } out: krb5_config_free_strings(rules); return ctx.result; }
KRB5_LIB_FUNCTION void KRB5_LIB_CALL _krb5_load_db_plugins(krb5_context context) { heim_base_once_f(&db_plugins_once, context, db_plugins_init); }