Nuances of MIT Kerberos prompting

Russ Allbery eagle at eyrie.org
Mon Mar 9 01:32:54 EDT 2020


Greg Hudson <ghudson at mit.edu> writes:
> On 3/8/20 8:01 PM, Russ Allbery wrote:

>> I think the reason why I am confused by this is that Heimdal uses the
>> prompter to pass along informational messages such as "your principal
>> is about to expire," and I wasn't sure how MIT Kerberos would do the
>> same thing with the responder interface.  But maybe it doesn't present
>> those messages, or uses the prompter for them even if a responder is
>> provided and answers the actual questions?

> In MIT krb5 you can set an expire callback
> (krb5_get_init_creds_opt_set_expire_callback()); otherwise the prompter
> is used if present, whether or not a responder is provided.

Oh!  Okay, that makes sense.  In this case, the prompter is called with
just a banner but no question?

> Yeah, I don't see an explanation there.  A PKINIT PKCS12 prompter call
> should be preceded by a "PKINIT initial PKCS12_parse with no password
> failed" message.  There are two such trace messages, but the first comes
> during prep_questions(), when prompting is deferred (instead, the
> identity is saved and a question for the responder is generated).

I was wrong -- it's not during verify creds.  (I finally realized that I
had enough information that I could set a break point exactly where this
happens and look at the call structure.)  It appears to be called twice
during krb5_get_init_creds_password.  Here are the Kerberos library
portions of the two backtraces (the prompt in both cases is identical).
This is MIT Kerberos 1.17.

The relevant difference seems to be in frame 4 and frame 5.  Source
embedded from the krb5-1.17-final tag.  In both cases, k5_preauth then
calls the responder.

#3  0x00007ffff7f2fc9b in k5_preauth (context=context at entry=0x555555594810,
    ctx=ctx at entry=0x555555595710, in_padata=0x555555570bd0,
    must_preauth=must_preauth at entry=1, padata_out=0x555555595928,
    pa_type_out=pa_type_out at entry=0x5555555958e8)
    at ../../../../src/lib/krb5/krb/preauth2.c:1061
#4  0x00007ffff7f22397 in init_creds_step_request (out=0x7fffffffc8e0,
    ctx=0x555555595710, context=0x555555594810)
    at ../../../../src/lib/krb5/krb/get_in_tkt.c:1398

    if (ctx->request->padata == NULL && ctx->method_padata != NULL) {
        /* Retrying after KDC_ERR_PREAUTH_REQUIRED, or trying again with a
         * different mechanism after a failure. */
        TRACE_INIT_CREDS_PREAUTH(context);
        code = k5_preauth(context, ctx, ctx->method_padata, TRUE,
                          &ctx->request->padata, &ctx->selected_preauth_type);
        if (code) {
            if (save.code != 0)
                code = k5_restore_ctx_error(context, &save);
            goto cleanup;
        }
    }

#5  krb5_init_creds_step (flags=0x7fffffffc8d8, realm=0x7fffffffc900,
    out=0x7fffffffc8e0, in=<optimized out>, ctx=0x555555595710,
    context=0x555555594810) at ../../../../src/lib/krb5/krb/get_in_tkt.c:1767

    code = init_creds_step_request(context, ctx, out);
    if (code != 0)
        goto cleanup;

#6  krb5_init_creds_step (context=0x555555594810, ctx=0x555555595710,
    in=<optimized out>, out=0x7fffffffc8e0, realm=0x7fffffffc900,
    flags=0x7fffffffc8d8) at ../../../../src/lib/krb5/krb/get_in_tkt.c:1727
#7  0x00007ffff7f230b9 in k5_init_creds_get (
    context=context at entry=0x555555594810, ctx=0x555555595710,
    use_master=use_master at entry=0x7fffffffca98)
    at ../../../../src/lib/krb5/krb/get_in_tkt.c:608
#8  0x00007ffff7f23214 in k5_get_init_creds (
    context=context at entry=0x555555594810, creds=creds at entry=0x555555594cc0,
    client=client at entry=0x555555596a30, prompter=prompter at entry=0x0,
    prompter_data=prompter_data at entry=0x555555592d30,
    start_time=start_time at entry=0, in_tkt_service=0x0, options=0x555555594d40, 
    gak_fct=0x7ffff7f24750 <krb5_get_as_key_password>, 
    gak_data=0x7fffffffcb00, use_master=0x7fffffffca98,
    as_reply=0x7fffffffcaa0) at ../../../../src/lib/krb5/krb/get_in_tkt.c:1833
#9  0x00007ffff7f24d39 in krb5_get_init_creds_password (
    context=0x555555594810, creds=0x555555594cc0, client=0x555555596a30,
    password=password at entry=0x0, prompter=prompter at entry=0x0,
    data=data at entry=0x555555592d30, start_time=0, in_tkt_service=0x0,
    options=0x555555594d40) at ../../../../src/lib/krb5/krb/gic_pwd.c:317


#3  0x00007ffff7f2fc9b in k5_preauth (context=context at entry=0x555555594810,
    ctx=ctx at entry=0x555555595710, in_padata=0x55555559b210, must_preauth=0,
    padata_out=padata_out at entry=0x7fffffffc800,
    pa_type_out=pa_type_out at entry=0x7fffffffc7f4)
    at ../../../../src/lib/krb5/krb/preauth2.c:1061
#4  0x00007ffff7f21cab in init_creds_step_reply (in=<optimized out>,
    ctx=0x555555595710, context=0x555555594810)
    at ../../../../src/lib/krb5/krb/get_in_tkt.c:1638

    /* Process the final reply padata.  Don't restrict the preauth types or
     * record a selected preauth type. */
    ctx->allowed_preauth_type = KRB5_PADATA_NONE;
    code = k5_preauth(context, ctx, ctx->reply->padata, FALSE, &kdc_padata,
                      &kdc_pa_type);
    if (code != 0)
        goto cleanup;

#5  krb5_init_creds_step (flags=0x7fffffffc8d8, realm=0x7fffffffc900,
    out=0x7fffffffc8e0, in=<optimized out>, ctx=0x555555595710,
    context=0x555555594810) at ../../../../src/lib/krb5/krb/get_in_tkt.c:1752

    if (in->length != 0) {
        code = init_creds_step_reply(context, ctx, in);
        if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG) {
            code2 = krb5int_copy_data_contents(context,
                                               ctx->encoded_previous_request,
                                               out);

#6  krb5_init_creds_step (context=0x555555594810, ctx=0x555555595710,
    in=<optimized out>, out=0x7fffffffc8e0, realm=0x7fffffffc900,
    flags=0x7fffffffc8d8) at ../../../../src/lib/krb5/krb/get_in_tkt.c:1727
#7  0x00007ffff7f230b9 in k5_init_creds_get (
    context=context at entry=0x555555594810, ctx=0x555555595710,
    use_master=use_master at entry=0x7fffffffca98)
    at ../../../../src/lib/krb5/krb/get_in_tkt.c:608
#8  0x00007ffff7f23214 in k5_get_init_creds (
    context=context at entry=0x555555594810, creds=creds at entry=0x555555594cc0,
    client=client at entry=0x555555596a30, prompter=prompter at entry=0x0,
    prompter_data=prompter_data at entry=0x555555592d30,
    start_time=start_time at entry=0, in_tkt_service=0x0, options=0x555555594d40,
    gak_fct=0x7ffff7f24750 <krb5_get_as_key_password>,
    gak_data=0x7fffffffcb00, use_master=0x7fffffffca98,
    as_reply=0x7fffffffcaa0) at ../../../../src/lib/krb5/krb/get_in_tkt.c:1833
#9  0x00007ffff7f24d39 in krb5_get_init_creds_password (
    context=0x555555594810, creds=0x555555594cc0, client=0x555555596a30,
    password=password at entry=0x0, prompter=prompter at entry=0x0,
    data=data at entry=0x555555592d30, start_time=0, in_tkt_service=0x0,
    options=0x555555594d40) at ../../../../src/lib/krb5/krb/gic_pwd.c:317

It looks like it calls the responder at two different points during the
entire preauth exchange?

Note that this may soon be irrelevant to this particular code base since
I'm probably going to switch back to a prompter.

-- 
Russ Allbery (eagle at eyrie.org)             <https://www.eyrie.org/~eagle/>


More information about the Kerberos mailing list