krb5_error_code k5_pwqual_load(krb5_context context, const char *dict_file, pwqual_handle **handles_out) { krb5_error_code ret; krb5_plugin_initvt_fn *modules = NULL, *mod; size_t count; pwqual_handle *list = NULL, handle = NULL; *handles_out = NULL; ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_PWQUAL, &modules); if (ret != 0) goto cleanup; /* Allocate a large enough list of handles. */ for (count = 0; modules[count] != NULL; count++); list = k5alloc((count + 1) * sizeof(*list), &ret); if (list == NULL) goto cleanup; /* For each module, allocate a handle, initialize its vtable, and bind the * dictionary filename. */ count = 0; for (mod = modules; *mod != NULL; mod++) { handle = k5alloc(sizeof(*handle), &ret); if (handle == NULL) goto cleanup; ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&handle->vt); if (ret != 0) { /* Failed vtable init is non-fatal. */ free(handle); handle = NULL; continue; } handle->data = NULL; if (handle->vt.open != NULL) { ret = handle->vt.open(context, dict_file, &handle->data); if (ret != 0) /* Failed dictionary binding is fatal. */ goto cleanup; } list[count++] = handle; list[count] = NULL; handle = NULL; } list[count] = NULL; ret = 0; *handles_out = list; list = NULL; cleanup: free(handle); k5_plugin_free_modules(context, modules); k5_pwqual_free_handles(context, list); return ret; }
krb5_error_code k5_kadm5_hook_load(krb5_context context, kadm5_hook_handle **handles_out) { krb5_error_code ret; krb5_plugin_initvt_fn *modules = NULL, *mod; size_t count; kadm5_hook_handle *list = NULL, handle = NULL; *handles_out = NULL; ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KADM5_HOOK, &modules); if (ret != 0) goto cleanup; /* Allocate a large enough list of handles. */ for (count = 0; modules[count] != NULL; count++); list = k5alloc((count + 1) * sizeof(*list), &ret); if (list == NULL) goto cleanup; /* For each module, allocate a handle, initialize its vtable, and * initialize the module. */ count = 0; for (mod = modules; *mod != NULL; mod++) { handle = k5alloc(sizeof(*handle), &ret); if (handle == NULL) goto cleanup; ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&handle->vt); if (ret != 0) { /* Failed vtable init is non-fatal. */ free(handle); handle = NULL; continue; } handle->data = NULL; if (handle->vt.init != NULL) { ret = handle->vt.init(context, &handle->data); if (ret != 0) /* Failed initialization is fatal. */ goto cleanup; } list[count++] = handle; list[count] = NULL; handle = NULL; } list[count] = NULL; ret = 0; *handles_out = list; list = NULL; cleanup: free(handle); k5_plugin_free_modules(context, modules); k5_kadm5_hook_free_handles(context, list); return ret; }
/* Initialize context->hostrealm_handles with a list of module handles. */ static krb5_error_code load_hostrealm_modules(krb5_context context) { krb5_error_code ret; struct hostrealm_module_handle **list = NULL, *handle; krb5_plugin_initvt_fn *modules = NULL, *mod; size_t count; ret = get_modules(context, &modules); if (ret != 0) goto cleanup; /* Allocate a large enough list of handles. */ for (count = 0; modules[count] != NULL; count++); list = k5alloc((count + 1) * sizeof(*list), &ret); if (list == NULL) goto cleanup; /* Initialize each module, ignoring ones that fail. */ count = 0; for (mod = modules; *mod != NULL; mod++) { handle = k5alloc(sizeof(*handle), &ret); if (handle == NULL) goto cleanup; ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&handle->vt); if (ret != 0) { TRACE_HOSTREALM_VTINIT_FAIL(context, ret); free(handle); continue; } handle->data = NULL; if (handle->vt.init != NULL) { ret = handle->vt.init(context, &handle->data); if (ret != 0) { TRACE_HOSTREALM_INIT_FAIL(context, handle->vt.name, ret); free(handle); continue; } } list[count++] = handle; list[count] = NULL; } list[count] = NULL; ret = 0; context->hostrealm_handles = list; list = NULL; cleanup: k5_plugin_free_modules(context, modules); free_handles(context, list); return ret; }
int main(int argc, char **argv) { krb5_context ctx, ctx2; krb5_plugin_initvt_fn *mods; const krb5_enctype etypes1[] = { ENCTYPE_DES3_CBC_SHA1, 0 }; const krb5_enctype etypes2[] = { ENCTYPE_AES128_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }; krb5_prompt_type ptypes[] = { KRB5_PROMPT_TYPE_PASSWORD }; /* Copy a default context and verify the result. */ check(krb5_init_context(&ctx) == 0); check(krb5_copy_context(ctx, &ctx2) == 0); check_context(ctx2, ctx); krb5_free_context(ctx2); /* Set non-default values for all of the propagated fields in ctx. */ ctx->allow_weak_crypto = TRUE; check(krb5_set_default_in_tkt_ktypes(ctx, etypes1) == 0); check(krb5_set_default_tgs_enctypes(ctx, etypes2) == 0); check(krb5_set_debugging_time(ctx, 1234, 5678) == 0); check(krb5_cc_set_default_name(ctx, "defccname") == 0); check(krb5_set_default_realm(ctx, "defrealm") == 0); ctx->clockskew = 18; ctx->kdc_req_sumtype = CKSUMTYPE_NIST_SHA; ctx->default_ap_req_sumtype = CKSUMTYPE_HMAC_SHA1_96_AES128; ctx->default_safe_sumtype = CKSUMTYPE_HMAC_SHA1_96_AES256; ctx->kdc_default_options = KDC_OPT_FORWARDABLE; ctx->library_options = 0; ctx->profile_secure = TRUE; ctx->udp_pref_limit = 2345; ctx->use_conf_ktypes = TRUE; ctx->ignore_acceptor_hostname = TRUE; ctx->dns_canonicalize_hostname = CANONHOST_FALSE; free(ctx->plugin_base_dir); check((ctx->plugin_base_dir = strdup("/a/b/c/d")) != NULL); /* Also set some of the non-propagated fields. */ ctx->prompt_types = ptypes; check(k5_plugin_load_all(ctx, PLUGIN_INTERFACE_PWQUAL, &mods) == 0); k5_plugin_free_modules(ctx, mods); k5_setmsg(ctx, ENOMEM, "nooooooooo"); krb5_set_trace_callback(ctx, trace, ctx); /* Copy the intentionally messy context and verify the result. */ check(krb5_copy_context(ctx, &ctx2) == 0); check_context(ctx2, ctx); krb5_free_context(ctx2); krb5_free_context(ctx); return 0; }
/* Create the per-krb5_context context. This means loading the modules * if we haven't done that yet (applications which never obtain initial * credentials should never hit this routine), breaking up the module's * list of support pa_types so that we can iterate over the modules more * easily, and copying over the relevant parts of the module's table. */ void KRB5_CALLCONV krb5_init_preauth_context(krb5_context kcontext) { int n_tables, n_modules, i, count; krb5_plugin_initvt_fn *plugins = NULL, *pl; struct krb5_clpreauth_vtable_st *vtables = NULL, *vt; struct krb5_preauth_context_module_st *mod; krb5_preauth_context *context = NULL; krb5_clpreauth_moddata moddata; krb5_preauthtype pa_type, *pat; krb5_boolean first; krb5_clpreauth_modreq *rcpp; /* Only do this once for each krb5_context */ if (kcontext->preauth_context != NULL) return; /* Auto-register built-in modules. */ k5_plugin_register_dyn(kcontext, PLUGIN_INTERFACE_CLPREAUTH, "pkinit", "preauth"); k5_plugin_register(kcontext, PLUGIN_INTERFACE_CLPREAUTH, "encrypted_challenge", clpreauth_encrypted_challenge_initvt); k5_plugin_register(kcontext, PLUGIN_INTERFACE_CLPREAUTH, "encrypted_timestamp", clpreauth_encrypted_timestamp_initvt); k5_plugin_register(kcontext, PLUGIN_INTERFACE_CLPREAUTH, "sam2", clpreauth_sam2_initvt); k5_plugin_register(kcontext, PLUGIN_INTERFACE_CLPREAUTH, "otp", clpreauth_otp_initvt); /* Get all available clpreauth vtables. */ if (k5_plugin_load_all(kcontext, PLUGIN_INTERFACE_CLPREAUTH, &plugins)) return; for (count = 0; plugins[count] != NULL; count++); vtables = calloc(count, sizeof(*vtables)); if (vtables == NULL) goto cleanup; for (pl = plugins, n_tables = 0; *pl != NULL; pl++) { if ((*pl)(kcontext, 1, 2, (krb5_plugin_vtable)&vtables[n_tables]) == 0) n_tables++; } /* Count how many modules we ended up loading, and how many preauth * types we may claim to support as a result. */ n_modules = 0; for (i = 0; i < n_tables; i++) { for (count = 0; vtables[i].pa_type_list[count] > 0; count++); n_modules += count; } /* Allocate the space we need. */ context = malloc(sizeof(*context)); if (context == NULL) goto cleanup; context->modules = calloc(n_modules, sizeof(*context->modules)); if (context->modules == NULL) goto cleanup; /* fill in the structure */ n_modules = 0; for (i = 0; i < n_tables; i++) { vt = &vtables[i]; if ((vt->pa_type_list != NULL) && (vt->process != NULL)) { moddata = NULL; if (vt->init != NULL && vt->init(kcontext, &moddata) != 0) { #ifdef DEBUG fprintf(stderr, "init err, skipping module \"%s\"\n", vt->name); #endif continue; } rcpp = NULL; for (pat = vt->pa_type_list, first = TRUE; *pat > 0; pat++, first = FALSE) { pa_type = *pat; mod = &context->modules[n_modules]; mod->pa_type = pa_type; mod->enctypes = vt->enctype_list; mod->moddata = moddata; /* Only call client_fini once per plugin */ if (first) mod->client_fini = vt->fini; else mod->client_fini = NULL; mod->name = vt->name; mod->flags = (*vt->flags)(kcontext, pa_type); mod->use_count = 0; mod->client_prep_questions = vt->prep_questions; mod->client_process = vt->process; mod->client_tryagain = vt->tryagain; mod->client_supply_gic_opts = first ? vt->gic_opts : NULL; mod->modreq = NULL; /* * Only call request_init and request_fini once per plugin. * Only the first module within each plugin will ever * have request_context filled in. Every module within * the plugin will have its request_context_pp pointing * to that entry's request_context. That way all the * modules within the plugin share the same request_context */ if (first) { mod->client_req_init = vt->request_init; mod->client_req_fini = vt->request_fini; rcpp = &mod->modreq; } else { mod->client_req_init = NULL; mod->client_req_fini = NULL; } mod->modreq_p = rcpp; #ifdef DEBUG fprintf(stderr, "init module \"%s\", pa_type %d, flag %d\n", mod->name, mod->pa_type, mod->flags); #endif n_modules++; } } } context->n_modules = n_modules; /* Place the constructed preauth context into the krb5 context. */ kcontext->preauth_context = context; context = NULL; cleanup: if (context) free(context->modules); free(context); k5_plugin_free_modules(kcontext, plugins); free(vtables); }