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); }
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; }