static krb5_error_code test_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 ***out_pa_data) { struct client_state *st = (struct client_state *)moddata; struct client_request_state *reqst = (struct client_request_state *)modreq; krb5_error_code ret; krb5_keyblock *k; krb5_enc_data enc; krb5_data plain; const char *indstr; if (pa_data->length == 0) { /* This is an optimistic preauth test. Send a recognizable padata * value so the KDC knows not to expect a cookie. */ if (st->fail_optimistic) { k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced optimistic fail"); return KRB5_PREAUTH_FAILED; } *out_pa_data = make_pa_list("optimistic", 10); return 0; } else if (reqst->second_round_trip) { printf("2rt: %.*s\n", pa_data->length, pa_data->contents); if (st->fail_2rt) { k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced 2rt fail"); return KRB5_PREAUTH_FAILED; } } else if (pa_data->length == 6 && memcmp(pa_data->contents, "no key", 6) == 0) { printf("no key\n"); } else { /* This fails during s4u_identify_user(), so don't assert. */ ret = cb->get_as_key(context, rock, &k); if (ret) return ret; ret = alloc_data(&plain, pa_data->length); assert(!ret); enc.enctype = k->enctype; enc.ciphertext = make_data(pa_data->contents, pa_data->length); ret = krb5_c_decrypt(context, k, 1024, NULL, &enc, &plain); assert(!ret); printf("%.*s\n", plain.length, plain.data); free(plain.data); } reqst->second_round_trip = TRUE; indstr = (st->indicators != NULL) ? st->indicators : ""; *out_pa_data = make_pa_list(indstr, strlen(indstr)); return 0; }
static krb5_error_code encts_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 *padata, krb5_prompter_fct prompter, void *prompter_data, krb5_pa_data ***out_padata) { krb5_error_code ret; krb5_pa_enc_ts pa_enc; krb5_data *ts = NULL, *enc_ts = NULL; krb5_enc_data enc_data; krb5_pa_data **pa = NULL; krb5_keyblock *as_key; enc_data.ciphertext = empty_data(); ret = cb->get_as_key(context, rock, &as_key); if (ret) goto cleanup; TRACE_PREAUTH_ENC_TS_KEY_GAK(context, as_key); /* now get the time of day, and encrypt it accordingly */ ret = krb5_us_timeofday(context, &pa_enc.patimestamp, &pa_enc.pausec); if (ret) goto cleanup; ret = encode_krb5_pa_enc_ts(&pa_enc, &ts); if (ret) goto cleanup; ret = krb5_encrypt_helper(context, as_key, KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, ts, &enc_data); if (ret) goto cleanup; TRACE_PREAUTH_ENC_TS(context, pa_enc.patimestamp, pa_enc.pausec, ts, &enc_data.ciphertext); ret = encode_krb5_enc_data(&enc_data, &enc_ts); if (ret) goto cleanup; pa = k5alloc(2 * sizeof(krb5_pa_data *), &ret); if (pa == NULL) goto cleanup; pa[0] = k5alloc(sizeof(krb5_pa_data), &ret); if (pa[0] == NULL) goto cleanup; pa[0]->magic = KV5M_PA_DATA; pa[0]->pa_type = KRB5_PADATA_ENC_TIMESTAMP; pa[0]->length = enc_ts->length; pa[0]->contents = (krb5_octet *) enc_ts->data; enc_ts->data = NULL; pa[1] = NULL; *out_padata = pa; pa = NULL; cleanup: krb5_free_data(context, ts); krb5_free_data(context, enc_ts); free(enc_data.ciphertext.data); free(pa); return ret; }
static krb5_error_code ec_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 *padata, krb5_prompter_fct prompter, void *prompter_data, krb5_pa_data ***out_padata) { krb5_error_code retval = 0; krb5_keyblock *challenge_key = NULL, *armor_key, *as_key; armor_key = cb->fast_armor(context, rock); if (armor_key == NULL) return ENOENT; retval = cb->get_as_key(context, rock, &as_key); if (retval == 0 && padata->length) { krb5_enc_data *enc = NULL; krb5_data scratch; scratch.length = padata->length; scratch.data = (char *) padata->contents; retval = krb5_c_fx_cf2_simple(context,armor_key, "kdcchallengearmor", as_key, "challengelongterm", &challenge_key); if (retval == 0) retval = decode_krb5_enc_data(&scratch, &enc); scratch.data = NULL; if (retval == 0) { scratch.data = malloc(enc->ciphertext.length); scratch.length = enc->ciphertext.length; if (scratch.data == NULL) retval = ENOMEM; } if (retval == 0) retval = krb5_c_decrypt(context, challenge_key, KRB5_KEYUSAGE_ENC_CHALLENGE_KDC, NULL, enc, &scratch); /* * Per draft 11 of the preauth framework, the client MAY but is not * required to actually check the timestamp from the KDC other than to * confirm it decrypts. This code does not perform that check. */ if (scratch.data) krb5_free_data_contents(context, &scratch); /* If we had a callback to assert that the KDC is verified, we would * call it here. */ if (enc) krb5_free_enc_data(context, enc); } else if (retval == 0) { /*No padata; we send*/ krb5_enc_data enc; krb5_pa_data **pa = NULL; krb5_data *encoded_ts = NULL; krb5_pa_enc_ts ts; enc.ciphertext.data = NULL; /* Use the timestamp from the preauth-required error if possible. * This time should always be secured by the FAST channel. */ retval = cb->get_preauth_time(context, rock, FALSE, &ts.patimestamp, &ts.pausec); if (retval == 0) retval = encode_krb5_pa_enc_ts(&ts, &encoded_ts); if (retval == 0) retval = krb5_c_fx_cf2_simple(context, armor_key, "clientchallengearmor", as_key, "challengelongterm", &challenge_key); if (retval == 0) retval = krb5_encrypt_helper(context, challenge_key, KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT, encoded_ts, &enc); if (encoded_ts) krb5_free_data(context, encoded_ts); encoded_ts = NULL; if (retval == 0) { retval = encode_krb5_enc_data(&enc, &encoded_ts); krb5_free_data_contents(context, &enc.ciphertext); } if (retval == 0) { pa = calloc(2, sizeof(krb5_pa_data *)); if (pa == NULL) retval = ENOMEM; } if (retval == 0) { pa[0] = calloc(1, sizeof(krb5_pa_data)); if (pa[0] == NULL) retval = ENOMEM; } if (retval == 0) { pa[0]->length = encoded_ts->length; pa[0]->contents = (unsigned char *) encoded_ts->data; pa[0]->pa_type = KRB5_PADATA_ENCRYPTED_CHALLENGE; encoded_ts->data = NULL; *out_padata = pa; pa = NULL; } free(pa); krb5_free_data(context, encoded_ts); } if (challenge_key) krb5_free_keyblock(context, challenge_key); return retval; }
static krb5_error_code test_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 ***out_pa_data) { struct client_state *st = (struct client_state *)moddata; struct client_request_state *reqst = (struct client_request_state *)modreq; krb5_error_code ret; krb5_pa_data **list, *pa; krb5_keyblock *k; krb5_enc_data enc; krb5_data plain; const char *indstr; if (pa_data->length == 0) { /* This is an optimistic preauth test. Send a recognizable padata * value so the KDC knows not to expect a cookie. */ list = k5calloc(2, sizeof(*list), &ret); assert(!ret); pa = k5alloc(sizeof(*pa), &ret); assert(!ret); pa->pa_type = TEST_PA_TYPE; pa->contents = (uint8_t *)strdup("optimistic"); assert(pa->contents != NULL); pa->length = 10; list[0] = pa; list[1] = NULL; *out_pa_data = list; return 0; } else if (reqst->second_round_trip) { printf("2rt: %.*s\n", pa_data->length, pa_data->contents); } else if (pa_data->length == 6 && memcmp(pa_data->contents, "no key", 6) == 0) { printf("no key\n"); } else { /* This fails during s4u_identify_user(), so don't assert. */ ret = cb->get_as_key(context, rock, &k); if (ret) return ret; ret = alloc_data(&plain, pa_data->length); assert(!ret); enc.enctype = k->enctype; enc.ciphertext = make_data(pa_data->contents, pa_data->length); ret = krb5_c_decrypt(context, k, 1024, NULL, &enc, &plain); assert(!ret); printf("%.*s\n", plain.length, plain.data); free(plain.data); } reqst->second_round_trip = TRUE; indstr = (st->indicators != NULL) ? st->indicators : ""; list = k5calloc(2, sizeof(*list), &ret); assert(!ret); pa = k5alloc(sizeof(*pa), &ret); assert(!ret); pa->pa_type = TEST_PA_TYPE; pa->contents = (uint8_t *)strdup(indstr); assert(pa->contents != NULL); pa->length = strlen(indstr); list[0] = pa; list[1] = NULL; *out_pa_data = list; return 0; }
static krb5_error_code encts_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 *padata, krb5_prompter_fct prompter, void *prompter_data, krb5_pa_data ***out_padata) { krb5_error_code ret; krb5_pa_enc_ts pa_enc; krb5_data *ts = NULL, *enc_ts = NULL; krb5_enc_data enc_data; krb5_pa_data **pa = NULL; krb5_keyblock *as_key; enc_data.ciphertext = empty_data(); ret = cb->get_as_key(context, rock, &as_key); if (ret) goto cleanup; TRACE_PREAUTH_ENC_TS_KEY_GAK(context, as_key); /* * Try and use the timestamp of the preauth request, even if it's * unauthenticated. We could be fooled into making a preauth response for * a future time, but that has no security consequences other than the * KDC's audit logs. If kdc_timesync is not configured, then this will * just use local time. */ ret = cb->get_preauth_time(context, rock, TRUE, &pa_enc.patimestamp, &pa_enc.pausec); if (ret) goto cleanup; ret = encode_krb5_pa_enc_ts(&pa_enc, &ts); if (ret) goto cleanup; ret = krb5_encrypt_helper(context, as_key, KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, ts, &enc_data); if (ret) goto cleanup; TRACE_PREAUTH_ENC_TS(context, pa_enc.patimestamp, pa_enc.pausec, ts, &enc_data.ciphertext); ret = encode_krb5_enc_data(&enc_data, &enc_ts); if (ret) goto cleanup; pa = k5alloc(2 * sizeof(krb5_pa_data *), &ret); if (pa == NULL) goto cleanup; pa[0] = k5alloc(sizeof(krb5_pa_data), &ret); if (pa[0] == NULL) goto cleanup; pa[0]->magic = KV5M_PA_DATA; pa[0]->pa_type = KRB5_PADATA_ENC_TIMESTAMP; pa[0]->length = enc_ts->length; pa[0]->contents = (krb5_octet *) enc_ts->data; enc_ts->data = NULL; pa[1] = NULL; *out_padata = pa; pa = NULL; cleanup: krb5_free_data(context, ts); krb5_free_data(context, enc_ts); free(enc_data.ciphertext.data); free(pa); return ret; }