Esempio n. 1
0
static void
kdc_include_padata(krb5_context context, krb5_kdc_req *request,
                   krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
                   krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
                   krb5_kdcpreauth_edata_respond_fn respond, void *arg)
{
    krb5_error_code retval;
    krb5_keyblock *client_key = NULL;
    krb5_sam_challenge_2 sc2;
    int sam_type = 0;             /* unknown */
    krb5_db_entry *sam_db_entry = NULL, *client;
    krb5_data *encoded_challenge = NULL;
    krb5_pa_data *pa_data = NULL;

    memset(&sc2, 0, sizeof(sc2));

    client = cb->client_entry(context, rock);
    retval = sam_get_db_entry(context, client->princ, &sam_type,
                              &sam_db_entry);
    if (retval)
        goto cleanup;
    retval = cb->client_keys(context, rock, &client_key);
    if (retval)
        goto cleanup;
    if (client_key->enctype == 0) {
        retval = KRB5KDC_ERR_ETYPE_NOSUPP;
        com_err("krb5kdc", retval,
                "No client keys found in processing SAM2 challenge");
        goto cleanup;
    }

    if (sam_type == 0) {
        retval = KRB5_PREAUTH_BAD_TYPE;
        goto cleanup;
    }

    /*
     * Defer getting the key for the SAM principal associated with the client
     * until the mechanism-specific code.  The mechanism may want to get a
     * specific keytype.
     */

    switch (sam_type) {
#ifdef ARL_SECURID_PREAUTH
    case PA_SAM_TYPE_SECURID:
        retval = get_securid_edata_2(context, client, client_key, &sc2);
        if (retval)
            goto cleanup;
        break;
#endif  /* ARL_SECURID_PREAUTH */
#ifdef GRAIL_PREAUTH
    case PA_SAM_TYPE_GRAIL:
        retval = get_grail_edata(context, client, client_key, &sc2);
        if (retval)
            goto cleanup;
        break;
#endif /* GRAIL_PREAUTH */
    default:
        retval = KRB5_PREAUTH_BAD_TYPE;
        goto cleanup;
    }

    retval = encode_krb5_sam_challenge_2(&sc2, &encoded_challenge);
    if (retval) {
        com_err("krb5kdc", retval,
                "while encoding SECURID SAM_CHALLENGE_2");
        goto cleanup;
    }

    pa_data = k5alloc(sizeof(*pa_data), &retval);
    if (pa_data == NULL)
        goto cleanup;
    pa_data->magic = KV5M_PA_DATA;
    pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE_2;
    pa_data->contents = (krb5_octet *)encoded_challenge->data;
    pa_data->length = encoded_challenge->length;
    encoded_challenge->data = NULL;

cleanup:
    krb5_free_data(context, encoded_challenge);
    if (sam_db_entry)
        krb5_db_free_principal(context, sam_db_entry);
    cb->free_keys(context, rock, client_key);
    (*respond)(arg, retval, pa_data);
}
Esempio n. 2
0
static void
kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
                   krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
                   krb5_pa_data *pa_data, krb5_kdcpreauth_callbacks cb,
                   krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
                   krb5_kdcpreauth_verify_respond_fn respond, void *arg)
{
    krb5_error_code retval, saved_retval = 0;
    krb5_sam_response_2 *sr2 = NULL;
    krb5_data scratch, *scratch2, *e_data = NULL;
    char *client_name = NULL;
    krb5_sam_challenge_2 *out_sc2 = NULL;
    krb5_db_entry *client = cb->client_entry(context, rock);

    scratch.data = (char *) pa_data->contents;
    scratch.length = pa_data->length;

    retval = krb5_unparse_name(context, client->princ, &client_name);
    if (retval)
        goto cleanup;

    retval = decode_krb5_sam_response_2(&scratch, &sr2);
    if (retval) {
        com_err("krb5kdc",  retval,
                "while decoding SAM_RESPONSE_2 in verify_sam_response_2");
        sr2 = NULL;
        goto cleanup;
    }

    switch (sr2->sam_type) {
#ifdef ARL_SECURID_PREAUTH
    case PA_SAM_TYPE_SECURID:
        retval = verify_securid_data_2(context, client, sr2, enc_tkt_reply,
                                       pa_data, &out_sc2);
        if (retval)
            goto cleanup;
        break;
#endif  /* ARL_SECURID_PREAUTH */
#ifdef GRAIL_PREAUTH
    case PA_SAM_TYPE_GRAIL:
        retval = verify_grail_data(context, client, sr2, enc_tkt_reply,
                                   pa_data, &out_sc2);
        if (retval)
            goto cleanup;
        break;
#endif /* GRAIL_PREAUTH */
    default:
        retval = KRB5_PREAUTH_BAD_TYPE;
        com_err("krb5kdc", retval, "while verifying SAM 2 data");
        break;
    }

    /*
     * It is up to the method-specific verify routine to set the
     * ticket flags to indicate TKT_FLG_HW_AUTH and/or
     * TKT_FLG_PRE_AUTH.  Some methods may require more than one round
     * of dialog with the client and must return successfully from
     * their verify routine.  If does not set the TGT flags, the
     * required_preauth conditions will not be met and it will try
     * again to get enough preauth data from the client.  Do not set
     * TGT flags here.
     */
cleanup:
    /*
     * Note that e_data is an output even in error conditions.  If we
     * successfully encode the output e_data, we return whatever error is
     * received above.  Otherwise we return the encoding error.
     */
    saved_retval = retval;
    if (out_sc2) {
        krb5_pa_data pa_out;
        krb5_pa_data *pa_array[2];
        pa_array[0] = &pa_out;
        pa_array[1] = NULL;
        pa_out.pa_type = KRB5_PADATA_SAM_CHALLENGE_2;
        retval = encode_krb5_sam_challenge_2(out_sc2, &scratch2);
        krb5_free_sam_challenge_2(context, out_sc2);
        if (retval)
            goto encode_error;
        pa_out.contents = (krb5_octet *) scratch2->data;
        pa_out.length = scratch2->length;
        retval = encode_krb5_padata_sequence(pa_array, &e_data);
        krb5_free_data(context, scratch2);
    }
encode_error:
    krb5_free_sam_response_2(context, sr2);
    free(client_name);
    if (retval == 0)
        retval = saved_retval;

    (*respond)(arg, retval, NULL, NULL, NULL);
}
static krb5_error_code
kdc_include_padata(krb5_context context, krb5_kdc_req *request,
                   struct _krb5_db_entry_new *client,
                   struct _krb5_db_entry_new *server,
                   preauth_get_entry_data_proc get_entry_proc,
                   void *pa_module_context, krb5_pa_data *pa_data)
{
    krb5_error_code retval;
    krb5_data *client_keys_data = NULL;
    krb5_keyblock *client_key = NULL;
    krb5_sam_challenge_2 sc2;
    krb5_sam_challenge_2_body sc2b;
    int sam_type = 0;             /* unknown */
    krb5_db_entry *sam_db_entry = NULL;
    krb5_data *encoded_challenge = NULL;

    memset(&sc2, 0, sizeof(sc2));
    memset(&sc2b, 0, sizeof(sc2b));
    sc2b.magic = KV5M_SAM_CHALLENGE_2;
    sc2b.sam_type = sam_type;

    retval = sam_get_db_entry(context, client->princ, &sam_type,
                              &sam_db_entry);
    if (retval)
        return retval;
    retval = get_entry_proc(context, request, client,
                            krb5plugin_preauth_keys, &client_keys_data);
    if (retval)
        goto cleanup;
    client_key = (krb5_keyblock *) client_keys_data->data;
    if (client_key->enctype == 0) {
        retval = KRB5KDC_ERR_ETYPE_NOSUPP;
        com_err("krb5kdc", retval,
                "No client keys found in processing SAM2 challenge");
        goto cleanup;
    }

    if (sam_type == 0) {
        retval = KRB5_PREAUTH_BAD_TYPE;
        goto cleanup;
    }

    /*
     * Defer getting the key for the SAM principal associated with the client
     * until the mechanism-specific code.  The mechanism may want to get a
     * specific keytype.
     */

    switch (sam_type) {
#ifdef ARL_SECURID_PREAUTH
    case PA_SAM_TYPE_SECURID:
        retval = get_securid_edata_2(context, client, client_key, &sc2b, &sc2);
        if (retval)
            goto cleanup;

        retval = encode_krb5_sam_challenge_2(&sc2, &encoded_challenge);
        if (retval) {
            com_err("krb5kdc", retval,
                    "while encoding SECURID SAM_CHALLENGE_2");
            goto cleanup;
        }

        pa_data->magic = KV5M_PA_DATA;
        pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE_2;
        pa_data->contents = (krb5_octet *) encoded_challenge->data;
        pa_data->length = encoded_challenge->length;
        encoded_challenge->data = NULL;

        retval = 0;
        break;
#endif  /* ARL_SECURID_PREAUTH */
    default:
        retval = KRB5_PREAUTH_BAD_TYPE;
        goto cleanup;
    }

cleanup:
    krb5_free_data(context, encoded_challenge);
    if (sam_db_entry)
        krb5_db_free_principal(context, sam_db_entry);
    if (client_keys_data) {
        while (client_key->enctype) {
            krb5_free_keyblock_contents(context, client_key);
            client_key++;
        }
        krb5_free_data(context, client_keys_data);
    }
    return retval;
}