krb5 commit: Use local TGT for AD-SIGNTICKET processing

Greg Hudson ghudson at mit.edu
Mon Jun 15 16:44:00 EDT 2015


https://github.com/krb5/krb5/commit/0c6498b2b9f4f4ad8b9f224714c84714425f2ca3
commit 0c6498b2b9f4f4ad8b9f224714c84714425f2ca3
Author: Greg Hudson <ghudson at mit.edu>
Date:   Mon Mar 2 16:27:47 2015 -0500

    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

 src/kdc/do_as_req.c    |    1 +
 src/kdc/do_tgs_req.c   |    2 +-
 src/kdc/kdc_authdata.c |  111 +++++++++++++++++++++++++++++++-----------------
 src/kdc/kdc_util.h     |    1 +
 4 files changed, 75 insertions(+), 40 deletions(-)

diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 24231bb..c62f0b3 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 73b39e0..f6d5cd3 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 2055d03..204cd09 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 ac86806..0fa4fbb 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,


More information about the cvs-krb5 mailing list