diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/crypto/arcfour/arcfour.c | 11 | ||||
-rw-r--r-- | src/lib/crypto/arcfour/arcfour.h | 5 | ||||
-rw-r--r-- | src/lib/crypto/etypes.c | 8 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/asn1_k_encode.c | 6 | ||||
-rw-r--r-- | src/lib/krb5/asn.1/krb5_decode.c | 6 | ||||
-rw-r--r-- | src/lib/krb5/krb/Makefile.in | 4 | ||||
-rw-r--r-- | src/lib/krb5/krb/fast.c | 42 | ||||
-rw-r--r-- | src/lib/krb5/krb/fast.h | 9 | ||||
-rw-r--r-- | src/lib/krb5/krb/get_in_tkt.c | 39 | ||||
-rw-r--r-- | src/lib/krb5/krb/kfree.c | 1 | ||||
-rw-r--r-- | src/lib/krb5/krb/preauth2.c | 35 | ||||
-rw-r--r-- | src/lib/krb5/krb/t_ad_fx_armor.c | 36 |
12 files changed, 162 insertions, 40 deletions
diff --git a/src/lib/crypto/arcfour/arcfour.c b/src/lib/crypto/arcfour/arcfour.c index ea3129688a..8d35d7eefc 100644 --- a/src/lib/crypto/arcfour/arcfour.c +++ b/src/lib/crypto/arcfour/arcfour.c @@ -8,6 +8,8 @@ of RSA Data Security) */ #include "k5-int.h" #include "arcfour-int.h" +#include "../hash_provider/hash_provider.h" + const char *const krb5int_arcfour_l40 = "fortybits"; void @@ -304,3 +306,12 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, return (ret); } + krb5_error_code krb5int_arcfour_prf( + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out) + { + assert(out->length == 20); + return krb5_hmac(&krb5int_hash_sha1, key, 1, in, out); + } diff --git a/src/lib/crypto/arcfour/arcfour.h b/src/lib/crypto/arcfour/arcfour.h index e8ff203ca1..be408febc6 100644 --- a/src/lib/crypto/arcfour/arcfour.h +++ b/src/lib/crypto/arcfour/arcfour.h @@ -34,5 +34,10 @@ extern krb5_error_code krb5int_arcfour_string_to_key( extern const struct krb5_enc_provider krb5int_enc_arcfour; extern const struct krb5_aead_provider krb5int_aead_arcfour; + krb5_error_code krb5int_arcfour_prf( + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out); #endif /* ARCFOUR_H */ diff --git a/src/lib/crypto/etypes.c b/src/lib/crypto/etypes.c index e7f547b91a..debf585fa7 100644 --- a/src/lib/crypto/etypes.c +++ b/src/lib/crypto/etypes.c @@ -119,10 +119,10 @@ const struct krb5_keytypes krb5_enctypes_list[] = { "ArcFour with HMAC/md5", &krb5int_enc_arcfour, &krb5int_hash_md5, - 0, + 20, krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, krb5_arcfour_decrypt, krb5int_arcfour_string_to_key, - NULL, /*PRF*/ + krb5int_arcfour_prf, /*PRF*/ CKSUMTYPE_HMAC_MD5_ARCFOUR, &krb5int_aead_arcfour, 0 /*flags*/ }, @@ -131,10 +131,10 @@ const struct krb5_keytypes krb5_enctypes_list[] = { "Exportable ArcFour with HMAC/md5", &krb5int_enc_arcfour, &krb5int_hash_md5, - 0, + 20, krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, krb5_arcfour_decrypt, krb5int_arcfour_string_to_key, - NULL, /*PRF*/ + krb5int_arcfour_prf, /*PRF*/ CKSUMTYPE_HMAC_MD5_ARCFOUR, &krb5int_aead_arcfour, ETYPE_WEAK diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index efa75643d5..ed01b7560d 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -1211,7 +1211,7 @@ DEFFIELDTYPE(fast_req_padata, krb5_kdc_req, DEFPTRTYPE(ptr_fast_req_padata, fast_req_padata); static const struct field_info fast_req_fields[] = { - FIELDOF_NORM(krb5_fast_req, int32, fast_options, 0), + FIELDOF_NORM(krb5_fast_req, krb5_flags, fast_options, 0), FIELDOF_NORM( krb5_fast_req, ptr_fast_req_padata, req_body, 1), FIELDOF_NORM( krb5_fast_req, ptr_kdc_req_body, req_body, 2), }; @@ -1233,7 +1233,7 @@ DEFPTRTYPE( ptr_fast_finished, fast_finished); static const struct field_info fast_response_fields[] = { FIELDOF_NORM(krb5_fast_response, ptr_seqof_pa_data, padata, 0), - FIELDOF_OPT( krb5_fast_response, ptr_encryption_key, rep_key, 1, 1), + FIELDOF_OPT( krb5_fast_response, ptr_encryption_key, strengthen_key, 1, 1), FIELDOF_OPT( krb5_fast_response, ptr_fast_finished, finished, 2, 2), FIELDOF_NORM(krb5_fast_response, int32, nonce, 3), }; @@ -1242,7 +1242,7 @@ static unsigned int fast_response_optional (const void *p) { unsigned int optional = 0; const krb5_fast_response *val = p; - if (val->rep_key) + if (val->strengthen_key) optional |= (1u <<1); if (val->finished) optional |= (1u<<2); diff --git a/src/lib/krb5/asn.1/krb5_decode.c b/src/lib/krb5/asn.1/krb5_decode.c index 9080d97ec7..7a08ec8884 100644 --- a/src/lib/krb5/asn.1/krb5_decode.c +++ b/src/lib/krb5/asn.1/krb5_decode.c @@ -1114,7 +1114,7 @@ krb5_error_code decode_krb5_fast_req alloc_field(rep->req_body); clear_field(rep, req_body->padata); {begin_structure(); - get_field(rep->fast_options, 0, asn1_decode_int32); + get_field(rep->fast_options, 0, asn1_decode_krb5_flags); opt_field(rep->req_body->padata, 1, asn1_decode_sequence_of_pa_data); get_field(*(rep->req_body), 2, asn1_decode_kdc_req_body); end_structure(); } @@ -1137,10 +1137,10 @@ krb5_error_code decode_krb5_fast_response alloc_field(rep); clear_field(rep, finished); clear_field(rep, padata); - clear_field(rep,rep_key); + clear_field(rep,strengthen_key); {begin_structure(); get_field(rep->padata, 0, asn1_decode_sequence_of_pa_data); - opt_field(rep->rep_key, 1, asn1_decode_encryption_key_ptr); + opt_field(rep->strengthen_key, 1, asn1_decode_encryption_key_ptr); opt_field(rep->finished, 2, asn1_decode_fast_finished_ptr); get_field(rep->nonce, 3, asn1_decode_int32); end_structure(); } diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in index acc18f6f46..c5256b3137 100644 --- a/src/lib/krb5/krb/Makefile.in +++ b/src/lib/krb5/krb/Makefile.in @@ -271,6 +271,7 @@ SRCS= $(srcdir)/addr_comp.c \ $(srcdir)/srv_dec_tkt.c \ $(srcdir)/srv_rcache.c \ $(srcdir)/str_conv.c \ + $(srcdir)/t_ad_fx_armor.c \ $(srcdir)/tgtname.c \ $(srcdir)/unparse.c \ $(srcdir)/valid_times.c \ @@ -317,6 +318,9 @@ T_PRINC_OBJS= t_princ.o parse.o unparse.o t_walk_rtree: $(T_WALK_RTREE_OBJS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o t_walk_rtree $(T_WALK_RTREE_OBJS) $(KRB5_BASE_LIBS) +t_ad_fx_armor: t_ad_fx_armor.o + $(CC_LINK) -o $@ $< $(KRB5_BASE_LIBS) + t_authdata: t_authdata.o copy_auth.o $(CC_LINK) -o $@ $< copy_auth.o $(KRB5_BASE_LIBS) diff --git a/src/lib/krb5/krb/fast.c b/src/lib/krb5/krb/fast.c index e9f54be788..ef57e6d832 100644 --- a/src/lib/krb5/krb/fast.c +++ b/src/lib/krb5/krb/fast.c @@ -299,6 +299,8 @@ static krb5_error_code decrypt_fast_reply free(scratch.data); if (encrypted_response) krb5_free_enc_data(context, encrypted_response); + if (local_resp) + krb5_free_fast_response(context, local_resp); return retval; } @@ -376,9 +378,11 @@ krb5int_fast_process_error(krb5_context context, struct krb5int_fast_request_sta fast_response->padata = NULL; /* * If there is more than the fx_error padata, then we want - * to retry the error + * to retry the error if a cookie is present */ *retry = (*out_padata)[1] != NULL; + if (krb5int_find_pa_data(context, *out_padata, KRB5_PADATA_FX_COOKIE) == NULL) + *retry = 0; } if (fx_error) krb5_free_error(context, fx_error); @@ -408,14 +412,14 @@ krb5int_fast_process_error(krb5_context context, struct krb5int_fast_request_sta krb5_error_code krb5int_fast_process_response (krb5_context context, struct krb5int_fast_request_state *state, krb5_kdc_rep *resp, - krb5_keyblock **as_key) + krb5_keyblock **strengthen_key) { krb5_error_code retval = 0; krb5_fast_response *fast_response = NULL; krb5_data *encoded_ticket = NULL; krb5_boolean cksum_valid; krb5_clear_error_message(context); - *as_key = NULL; + *strengthen_key = NULL; if (state->armor_key == 0) return 0; retval = decrypt_fast_reply(context, state, resp->padata, @@ -442,8 +446,8 @@ krb5_error_code krb5int_fast_process_response krb5_free_principal(context, resp->client); resp->client = fast_response->finished->client; fast_response->finished->client = NULL; - *as_key = fast_response->rep_key; - fast_response->rep_key = NULL; + *strengthen_key = fast_response->strengthen_key; + fast_response->strengthen_key = NULL; krb5_free_pa_data(context, resp->padata); resp->padata = fast_response->padata; fast_response->padata = NULL; @@ -454,6 +458,29 @@ krb5_error_code krb5int_fast_process_response krb5_free_data(context, encoded_ticket); return retval; } + +krb5_error_code krb5int_fast_reply_key(krb5_context context, + krb5_keyblock *strengthen_key, + krb5_keyblock *existing_key, + krb5_keyblock *out_key) +{ + krb5_keyblock *key = NULL; + krb5_error_code retval = 0; + krb5_free_keyblock_contents(context, out_key); + if (strengthen_key) { + retval = krb5_c_fx_cf2_simple(context, strengthen_key, + "strengthenkey", existing_key, "replykey", &key); + if (retval == 0) { + *out_key = *key; + free(key); + } + } else { + retval = krb5_copy_keyblock_contents(context, existing_key, out_key); + } + return retval; +} + + krb5_error_code krb5int_fast_make_state( krb5_context context, struct krb5int_fast_request_state **state) { @@ -473,11 +500,6 @@ krb5int_fast_free_state( krb5_context context, struct krb5int_fast_request_state /*We are responsible for none of the store in the fast_outer_req*/ krb5_free_keyblock(context, state->armor_key); krb5_free_fast_armor(context, state->armor); - if (state->cookie) { - free(state->cookie->contents); - free(state->cookie); - state->cookie = NULL; - } free(state); } diff --git a/src/lib/krb5/krb/fast.h b/src/lib/krb5/krb/fast.h index e21df6504b..4cc142335e 100644 --- a/src/lib/krb5/krb/fast.h +++ b/src/lib/krb5/krb/fast.h @@ -38,7 +38,6 @@ struct krb5int_fast_request_state { krb5_fast_armor *armor; krb5_ui_4 fast_state_flags; krb5_ui_4 fast_options; - krb5_pa_data *cookie; krb5_int32 nonce; }; @@ -61,7 +60,7 @@ krb5int_fast_process_error(krb5_context context, struct krb5int_fast_request_sta krb5_error_code krb5int_fast_process_response (krb5_context context, struct krb5int_fast_request_state *state, krb5_kdc_rep *resp, - krb5_keyblock **as_key); + krb5_keyblock **strengthen_key); krb5_error_code krb5int_fast_make_state( krb5_context context, struct krb5int_fast_request_state **state); @@ -73,5 +72,11 @@ krb5_error_code krb5int_fast_as_armor krb5_gic_opt_ext *opte, krb5_kdc_req *request); +krb5_error_code krb5int_fast_reply_key(krb5_context context, + krb5_keyblock *strengthen_key, + krb5_keyblock *existing_key, + krb5_keyblock *output_key); + + #endif diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index 30a38cdae9..2944652ffc 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -967,8 +967,8 @@ krb5_get_init_creds(krb5_context context, int loopcount; krb5_data salt; krb5_data s2kparams; - krb5_keyblock as_key; - krb5_keyblock *fast_as_key = NULL; + krb5_keyblock as_key, encrypting_key; + krb5_keyblock *strengthen_key = NULL; krb5_error *err_reply; krb5_kdc_rep *local_as_reply; krb5_timestamp time_now; @@ -994,6 +994,8 @@ krb5_get_init_creds(krb5_context context, preauth_to_use = NULL; kdc_padata = NULL; as_key.length = 0; + encrypting_key.length = 0; + encrypting_key.contents = NULL; salt.length = 0; salt.data = NULL; @@ -1340,8 +1342,6 @@ krb5_get_init_creds(krb5_context context, out_padata = NULL; krb5_free_error(context, err_reply); err_reply = NULL; - if (ret) - goto cleanup; ret = sort_krb5_padata_sequence(context, &request.server->realm, preauth_to_use); @@ -1399,7 +1399,7 @@ krb5_get_init_creds(krb5_context context, /* process any preauth data in the as_reply */ krb5_clear_preauth_context_use_counts(context); ret = krb5int_fast_process_response(context, fast_state, - local_as_reply, &fast_as_key); + local_as_reply, &strengthen_key); if (ret) goto cleanup; if ((ret = sort_krb5_padata_sequence(context, &request.server->realm, @@ -1447,18 +1447,15 @@ krb5_get_init_creds(krb5_context context, it. If decrypting the as_rep fails, or if there isn't an as_key at all yet, then use the gak_fct to get one, and try again. */ - if (fast_as_key) { - if (as_key.length) - krb5_free_keyblock_contents(context, &as_key); - as_key = *fast_as_key; - free(fast_as_key); - fast_as_key = NULL; - } - if (as_key.length) - ret = decrypt_as_reply(context, NULL, local_as_reply, NULL, - NULL, &as_key, krb5_kdc_rep_decrypt_proc, + if (as_key.length) { + ret = krb5int_fast_reply_key(context, strengthen_key, &as_key, + &encrypting_key); + if (ret) + goto cleanup; + ret = decrypt_as_reply(context, NULL, local_as_reply, NULL, + NULL, &encrypting_key, krb5_kdc_rep_decrypt_proc, NULL); - else + } else ret = -1; if (ret) { @@ -1470,6 +1467,10 @@ krb5_get_init_creds(krb5_context context, &as_key, gak_data)))) goto cleanup; + ret = krb5int_fast_reply_key(context, strengthen_key, &as_key, + &encrypting_key); + if (ret) + goto cleanup; if ((ret = decrypt_as_reply(context, NULL, local_as_reply, NULL, NULL, &as_key, krb5_kdc_rep_decrypt_proc, NULL))) @@ -1511,8 +1512,10 @@ cleanup: } } krb5_preauth_request_context_fini(context); - krb5_free_keyblock(context, fast_as_key); - if (fast_state) + krb5_free_keyblock(context, strengthen_key); + if (encrypting_key.contents) + krb5_free_keyblock_contents(context, &encrypting_key); + if (fast_state) krb5int_fast_free_state(context, fast_state); if (out_padata) krb5_free_pa_data(context, out_padata); diff --git a/src/lib/krb5/krb/kfree.c b/src/lib/krb5/krb/kfree.c index d17d46bc7d..bec9a61bfa 100644 --- a/src/lib/krb5/krb/kfree.c +++ b/src/lib/krb5/krb/kfree.c @@ -819,6 +819,7 @@ void krb5_free_fast_response(krb5_context context, krb5_fast_response *val) return; krb5_free_pa_data(context, val->padata); krb5_free_fast_finished(context, val->finished); + krb5_free_keyblock(context, val->strengthen_key); free(val); } diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c index 4c7dd5e607..73f4e79b61 100644 --- a/src/lib/krb5/krb/preauth2.c +++ b/src/lib/krb5/krb/preauth2.c @@ -646,6 +646,36 @@ krb5_error_code pa_salt(krb5_context context, } static +krb5_error_code pa_fx_cookie(krb5_context context, + krb5_kdc_req *request, + krb5_pa_data *in_padata, + krb5_pa_data **out_padata, + krb5_data *salt, + krb5_data *s2kparams, + krb5_enctype *etype, + krb5_keyblock *as_key, + krb5_prompter_fct prompter, + void *prompter_data, + krb5_gic_get_as_key_fct gak_fct, + void *gak_data) +{ + krb5_pa_data *pa = calloc(1, sizeof(krb5_pa_data)); + krb5_octet *contents; + if (pa == NULL) + return ENOMEM; + contents = malloc(in_padata->length); + if (contents == NULL) { + free(pa); + return ENOMEM; + } + *pa = *in_padata; + pa->contents = contents; + memcpy(contents, in_padata->contents, pa->length); + *out_padata = pa; + return 0; +} + +static krb5_error_code pa_enc_timestamp(krb5_context context, krb5_kdc_req *request, krb5_pa_data *in_padata, @@ -1710,6 +1740,11 @@ static const pa_types_t pa_types[] = { PA_REAL, }, { + KRB5_PADATA_FX_COOKIE, + pa_fx_cookie, + PA_INFO, + }, + { -1, NULL, 0, diff --git a/src/lib/krb5/krb/t_ad_fx_armor.c b/src/lib/krb5/krb/t_ad_fx_armor.c new file mode 100644 index 0000000000..74d7e5f1ab --- /dev/null +++ b/src/lib/krb5/krb/t_ad_fx_armor.c @@ -0,0 +1,36 @@ +#include <memory.h> +#include <stdio.h> +#include <krb5/krb5.h> + +#define test(x) do {retval = (x); \ + if(retval != 0) { \ + const char *errmsg = krb5_get_error_message(context, retval); \ + fprintf(stderr, "Error message: %s\n", errmsg); \ + abort(); } \ + } while(0); + +krb5_authdata ad_fx_armor = {0, KRB5_AUTHDATA_FX_ARMOR, 1, ""}; +krb5_authdata *array[] = {&ad_fx_armor, NULL}; + + +int main( int argc, char **argv) +{ + krb5_context context; + krb5_ccache ccache = NULL; + krb5_creds creds, *out_creds = NULL; + krb5_error_code retval = 0; + test(krb5_init_context(&context)); + memset(&creds, 0, sizeof(creds)); + creds.authdata = array; + test(krb5_cc_default(context, &ccache)); + test(krb5_cc_get_principal(context, ccache, &creds.client)); + test(krb5_parse_name(context, argv[1], &creds.server)); + test(krb5_get_credentials(context, 0, ccache, &creds, &out_creds)); + test(krb5_cc_destroy(context, ccache)); + test(krb5_cc_default(context, &ccache)); + test(krb5_cc_initialize(context, ccache, out_creds->client)); + test(krb5_cc_store_cred(context, ccache, out_creds)); + test(krb5_cc_close(context,ccache)); + return 0; + +} |