/* Get the registered hostrealm modules including all built-in modules, in the * proper order. */ static krb5_error_code get_modules(krb5_context context, krb5_plugin_initvt_fn **modules_out) { krb5_error_code ret; const int intf = PLUGIN_INTERFACE_HOSTREALM; *modules_out = NULL; /* Register built-in modules. */ ret = k5_plugin_register(context, intf, "profile", hostrealm_profile_initvt); if (ret) return ret; ret = k5_plugin_register(context, intf, "registry", hostrealm_registry_initvt); if (ret) return ret; ret = k5_plugin_register(context, intf, "dns", hostrealm_dns_initvt); if (ret) return ret; ret = k5_plugin_register(context, intf, "domain", hostrealm_domain_initvt); if (ret) return ret; return k5_plugin_load_all(context, intf, modules_out); }
int main() { krb5_plugin_initvt_fn *modules = NULL, *mod; struct krb5_pwqual_vtable_st vt; check(krb5_init_context(&ctx)); check(k5_plugin_register(ctx, PLUGIN_INTERFACE_PWQUAL, "blt1", blt1)); check(k5_plugin_register(ctx, PLUGIN_INTERFACE_PWQUAL, "blt2", blt2)); check(k5_plugin_register(ctx, PLUGIN_INTERFACE_PWQUAL, "blt3", blt3)); check(k5_plugin_load_all(ctx, PLUGIN_INTERFACE_PWQUAL, &modules)); for (mod = modules; *mod != NULL; mod++) { check((*mod)(ctx, 1, 1, (krb5_plugin_vtable)&vt)); printf("%s\n", vt.name); } 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); }