From: Greg Hudson Date: Mon, 2 Mar 2015 21:27:47 +0000 (-0500) Subject: Use local TGT for AD-SIGNTICKET processing X-Git-Tag: krb5-1.14-alpha1~102 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0c6498b2b9f4f4ad8b9f224714c84714425f2ca3;p=thirdparty%2Fkrb5.git Use local TGT for AD-SIGNTICKET processing Always use the first key of the local TGT to create the AD-SIGNTICKET checksum, and try the first key of the last three kvnos of the local TGT to verify the checksum. ticket: 8139 --- diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 24231bb4db..c62f0b39d5 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -263,6 +263,7 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) state->client, state->server, NULL, + state->local_tgt, &state->client_keyblock, &state->server_keyblock, NULL, diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 73b39e0da0..f6d5cd3852 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -650,7 +650,7 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt, } errcode = handle_authdata(kdc_context, c_flags, client, server, - header_server, + header_server, local_tgt, subkey != NULL ? subkey : header_ticket->enc_part2->session, &encrypting_key, /* U2U or server key */ diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c index 2055d03711..204cd09cf6 100644 --- a/src/kdc/kdc_authdata.c +++ b/src/kdc/kdc_authdata.c @@ -435,16 +435,22 @@ make_signedpath_data(krb5_context context, krb5_const_principal client, } static krb5_error_code -verify_signedpath_checksum(krb5_context context, krb5_keyblock *krbtgt_key, +verify_signedpath_checksum(krb5_context context, krb5_db_entry *local_tgt, krb5_enc_tkt_part *enc_tkt_part, krb5_principal *deleg_path, krb5_pa_data **method_data, krb5_checksum *cksum, - krb5_boolean *valid) + krb5_boolean *valid_out) { krb5_error_code ret; krb5_data *data; + krb5_key_data *kd; + krb5_keyblock tgtkey; + krb5_kvno kvno; + krb5_boolean valid = FALSE; + int tries; - *valid = FALSE; + *valid_out = FALSE; + memset(&tgtkey, 0, sizeof(tgtkey)); if (!krb5_c_is_keyed_cksum(cksum->checksum_type)) return KRB5KRB_AP_ERR_INAPP_CKSUM; @@ -456,16 +462,40 @@ verify_signedpath_checksum(krb5_context context, krb5_keyblock *krbtgt_key, if (ret) return ret; - ret = krb5_c_verify_checksum(context, krbtgt_key, - KRB5_KEYUSAGE_AD_SIGNEDPATH, data, cksum, - valid); + /* There is no kvno in AD-SIGNTICKET, so try the last three versions. */ + kvno = 0; + tries = 3; + do { + /* Get the first local tgt key of this kvno (highest kvno for the first + * iteration). */ + ret = krb5_dbe_find_enctype(context, local_tgt, -1, -1, kvno, &kd); + if (ret) { + ret = 0; + break; + } + ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &tgtkey, NULL); + if (ret) + break; + + ret = krb5_c_verify_checksum(context, &tgtkey, + KRB5_KEYUSAGE_AD_SIGNEDPATH, data, cksum, + &valid); + krb5_free_keyblock_contents(context, &tgtkey); + if (!ret && valid) + break; + + /* Try the next lower kvno on the next iteration. */ + kvno = kd->key_data_kvno - 1; + } while (--tries > 0 && kvno > 0); + + *valid_out = valid; krb5_free_data(context, data); return ret; } static krb5_error_code -verify_signedpath(krb5_context context, krb5_keyblock *krbtgt_key, +verify_signedpath(krb5_context context, krb5_db_entry *local_tgt, krb5_enc_tkt_part *enc_tkt_part, krb5_principal **delegated_out, krb5_boolean *pathsigned_out) { @@ -498,7 +528,7 @@ verify_signedpath(krb5_context context, krb5_keyblock *krbtgt_key, goto cleanup; } - ret = verify_signedpath_checksum(context, krbtgt_key, enc_tkt_part, + ret = verify_signedpath_checksum(context, local_tgt, enc_tkt_part, sp->delegated, sp->method_data, &sp->checksum, pathsigned_out); if (ret) @@ -518,45 +548,51 @@ cleanup: static krb5_error_code make_signedpath_checksum(krb5_context context, krb5_const_principal for_user_princ, - krb5_keyblock *krbtgt_key, + krb5_db_entry *local_tgt, krb5_enc_tkt_part *enc_tkt_part, krb5_principal *deleg_path, - krb5_pa_data **method_data, krb5_checksum *cksum) + krb5_pa_data **method_data, krb5_checksum *cksum_out, + krb5_enctype *enctype_out) { krb5_error_code ret; krb5_data *data; - krb5_cksumtype cksumtype; krb5_const_principal client; + krb5_key_data *kd; + krb5_keyblock tgtkey; + + memset(&tgtkey, 0, sizeof(tgtkey)); + memset(cksum_out, 0, sizeof(*cksum_out)); + *enctype_out = ENCTYPE_NULL; client = (for_user_princ != NULL) ? for_user_princ : enc_tkt_part->client; + /* Get the first local tgt key of the highest kvno. */ + ret = krb5_dbe_find_enctype(context, local_tgt, -1, -1, 0, &kd); + if (ret) + goto cleanup; + ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &tgtkey, NULL); + if (ret) + goto cleanup; + ret = make_signedpath_data(context, client, enc_tkt_part->times.authtime, deleg_path, method_data, enc_tkt_part->authorization_data, &data); if (ret) - return ret; - - ret = krb5int_c_mandatory_cksumtype(context, krbtgt_key->enctype, - &cksumtype); - if (ret) { - krb5_free_data(context, data); - return ret; - } + goto cleanup; - if (!krb5_c_is_keyed_cksum(cksumtype)) { - krb5_free_data(context, data); - return KRB5KRB_AP_ERR_INAPP_CKSUM; - } + ret = krb5_c_make_checksum(context, 0, &tgtkey, + KRB5_KEYUSAGE_AD_SIGNEDPATH, data, cksum_out); + *enctype_out = tgtkey.enctype; - ret = krb5_c_make_checksum(context, cksumtype, krbtgt_key, - KRB5_KEYUSAGE_AD_SIGNEDPATH, data, cksum); +cleanup: krb5_free_data(context, data); + krb5_free_keyblock_contents(context, &tgtkey); return ret; } static krb5_error_code make_signedpath(krb5_context context, krb5_const_principal for_user_princ, - krb5_principal server, krb5_keyblock *krbtgt_key, + krb5_principal server, krb5_db_entry *local_tgt, krb5_principal *deleg_path, krb5_enc_tkt_part *enc_tkt_reply) { krb5_error_code ret; @@ -568,8 +604,6 @@ make_signedpath(krb5_context context, krb5_const_principal for_user_princ, memset(&sp, 0, sizeof(sp)); - sp.enctype = krbtgt_key->enctype; - for (count = 0; deleg_path != NULL && deleg_path[count] != NULL; count++); sp.delegated = k5calloc(count + 2, sizeof(krb5_principal), &ret); @@ -584,9 +618,9 @@ make_signedpath(krb5_context context, krb5_const_principal for_user_princ, sp.delegated[count] = NULL; sp.method_data = NULL; - ret = make_signedpath_checksum(context, for_user_princ, krbtgt_key, + ret = make_signedpath_checksum(context, for_user_princ, local_tgt, enc_tkt_reply, sp.delegated, sp.method_data, - &sp.checksum); + &sp.checksum, &sp.enctype); if (ret) { if (ret == KRB5KRB_AP_ERR_INAPP_CKSUM) { /* @@ -656,7 +690,7 @@ only_pac_p(krb5_context context, krb5_authdata **authdata) static krb5_error_code handle_signticket(krb5_context context, unsigned int flags, krb5_db_entry *client, krb5_db_entry *server, - krb5_keyblock *krbtgt_key, krb5_kdc_req *req, + krb5_db_entry *local_tgt, krb5_kdc_req *req, krb5_const_principal for_user_princ, krb5_enc_tkt_part *enc_tkt_req, krb5_enc_tkt_part *enc_tkt_reply) @@ -674,7 +708,7 @@ handle_signticket(krb5_context context, unsigned int flags, */ if (req->msg_type == KRB5_TGS_REQ && !only_pac_p(context, enc_tkt_req->authorization_data)) { - ret = verify_signedpath(context, krbtgt_key, enc_tkt_req, &deleg_path, + ret = verify_signedpath(context, local_tgt, enc_tkt_req, &deleg_path, &signed_path); if (ret) goto cleanup; @@ -691,7 +725,7 @@ handle_signticket(krb5_context context, unsigned int flags, !is_cross_tgs_principal(server->princ) && !only_pac_p(context, enc_tkt_reply->authorization_data)) { ret = make_signedpath(context, for_user_princ, - s4u2proxy ? client->princ : NULL, krbtgt_key, + s4u2proxy ? client->princ : NULL, local_tgt, deleg_path, enc_tkt_reply); if (ret) goto cleanup; @@ -705,10 +739,10 @@ cleanup: krb5_error_code handle_authdata(krb5_context context, unsigned int flags, krb5_db_entry *client, krb5_db_entry *server, - krb5_db_entry *header_server, krb5_keyblock *client_key, - krb5_keyblock *server_key, krb5_keyblock *header_key, - krb5_data *req_pkt, krb5_kdc_req *req, - krb5_const_principal for_user_princ, + krb5_db_entry *header_server, krb5_db_entry *local_tgt, + krb5_keyblock *client_key, krb5_keyblock *server_key, + krb5_keyblock *header_key, krb5_data *req_pkt, + krb5_kdc_req *req, krb5_const_principal for_user_princ, krb5_enc_tkt_part *enc_tkt_req, krb5_enc_tkt_part *enc_tkt_reply) { @@ -757,8 +791,7 @@ handle_authdata(krb5_context context, unsigned int flags, /* Validate and insert AD-SIGNTICKET authdata. This must happen last * since it contains a signature over the other authdata. */ - ret = handle_signticket(context, flags, client, server, - (header_key != NULL) ? header_key : server_key, + ret = handle_signticket(context, flags, client, server, local_tgt, req, for_user_princ, enc_tkt_req, enc_tkt_reply); if (ret) diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index ac868065d1..0fa4fbb41f 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -216,6 +216,7 @@ handle_authdata (krb5_context context, krb5_db_entry *client, krb5_db_entry *server, krb5_db_entry *header_server, + krb5_db_entry *local_tgt, krb5_keyblock *client_key, krb5_keyblock *server_key, krb5_keyblock *header_key,