Ejemplo n.º 1
0
/* Set up context->tls.  On allocation failure, return ENOMEM.  On plugin load
 * failure, set context->tls to point to a nulled vtable and return 0. */
static krb5_error_code
init_tls_vtable(krb5_context context)
{
    krb5_plugin_initvt_fn initfn;

    if (context->tls != NULL)
        return 0;

    context->tls = calloc(1, sizeof(*context->tls));
    if (context->tls == NULL)
        return ENOMEM;

    /* Attempt to load the module; just let it stay nulled out on failure. */
    k5_plugin_register_dyn(context, PLUGIN_INTERFACE_TLS, "k5tls", "tls");
    if (k5_plugin_load(context, PLUGIN_INTERFACE_TLS, "k5tls", &initfn) == 0)
        (*initfn)(context, 0, 0, (krb5_plugin_vtable)context->tls);

    return 0;
}
Ejemplo n.º 2
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);
}