Exemplo n.º 1
0
static krb5_error_code
otp_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
                   krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,
                   krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
                   krb5_kdc_req *request, krb5_data *encoded_request_body,
                   krb5_data *encoded_previous_request, krb5_pa_data *pa_data,
                   krb5_prompter_fct prompter, void *prompter_data,
                   krb5_pa_data ***pa_data_out)
{
    krb5_pa_otp_challenge *chl = NULL;
    krb5_otp_tokeninfo *ti = NULL;
    krb5_keyblock *as_key = NULL;
    krb5_pa_otp_req *req = NULL;
    krb5_error_code retval = 0;
    krb5_data value, pin;
    const char *answer;

    if (modreq == NULL)
        return ENOMEM;
    chl = *(krb5_pa_otp_challenge **)modreq;

    *pa_data_out = NULL;

    /* Get FAST armor key. */
    as_key = cb->fast_armor(context, rock);
    if (as_key == NULL)
        return ENOENT;

    /* Use FAST armor key as response key. */
    retval = cb->set_as_key(context, rock, as_key);
    if (retval != 0)
        return retval;

    /* Attempt to get token selection from the responder. */
    pin = empty_data();
    value = empty_data();
    answer = cb->get_responder_answer(context, rock,
                                      KRB5_RESPONDER_QUESTION_OTP);
    retval = codec_decode_answer(context, answer, chl->tokeninfo, &ti, &value,
                                 &pin);
    if (retval != 0) {
        /* If the responder doesn't have a token selection,
         * we need to select the token via prompting. */
        retval = prompt_for_token(context, prompter, prompter_data,
                                  chl->tokeninfo, &ti, &value, &pin);
        if (retval != 0)
            goto error;
    }

    /* Make the request. */
    retval = make_request(context, ti, &value, &pin, &req);
    if (retval != 0)
        goto error;

    /* Save information about the token which was used. */
    save_config_tokeninfo(context, cb, rock, ti);

    /* Encrypt the challenge's nonce and set it in the request. */
    retval = encrypt_nonce(context, as_key, chl, req);
    if (retval != 0)
        goto error;

    /* Encode the request into the pa_data output. */
    retval = set_pa_data(req, pa_data_out);
error:
    krb5_free_data_contents(context, &value);
    krb5_free_data_contents(context, &pin);
    k5_free_pa_otp_req(context, req);
    return retval;
}