krb5 commit: Test that PAC is the first authdata element

Greg Hudson ghudson at mit.edu
Wed Feb 5 17:34:48 EST 2020


https://github.com/krb5/krb5/commit/d40d7c8ee8d7fb547e45c545365b21a818050130
commit d40d7c8ee8d7fb547e45c545365b21a818050130
Author: Isaac Boukris <iboukris at gmail.com>
Date:   Sat Feb 1 13:21:39 2020 +0100

    Test that PAC is the first authdata element
    
    In the test KDB module, set the PAC as the first authdata element.  In
    adata.c, add PAC service verification and verify that a PAC does not
    appear in authdata elements after the first.
    
    [ghudson at mit.edu: minor style changes; edited commit message]
    
    ticket: 8872

 src/plugins/kdb/test/kdb_test.c |    7 +++--
 src/tests/adata.c               |   54 +++++++++++++++++++++++++++++++++-----
 2 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c
index 4f8ea78..8aac306 100644
--- a/src/plugins/kdb/test/kdb_test.c
+++ b/src/plugins/kdb/test/kdb_test.c
@@ -922,10 +922,11 @@ test_sign_authdata(krb5_context context, unsigned int flags,
     test_ad->contents = (uint8_t *)estrdup("db-authdata-test");
     test_ad->length = strlen((char *)test_ad->contents);
 
-    /* Assemble the authdata into a one-element or two-element list. */
+    /* Assemble the authdata into a one-element or two-element list.
+     * The PAC must be the first element. */
     list = ealloc(3 * sizeof(*list));
-    list[0] = test_ad;
-    list[1] = pac_ad;
+    list[0] = (pac_ad != NULL) ? pac_ad : test_ad;
+    list[1] = (pac_ad != NULL) ? test_ad : NULL;
     list[2] = NULL;
     *signed_auth_data = list;
 
diff --git a/src/tests/adata.c b/src/tests/adata.c
index d3bd08e..3869aec 100644
--- a/src/tests/adata.c
+++ b/src/tests/adata.c
@@ -56,7 +56,8 @@
 static krb5_context ctx;
 
 static void display_authdata_list(krb5_authdata **list, krb5_keyblock *skey,
-                                  krb5_keyblock *tktkey, char prefix_byte);
+                                  krb5_keyblock *tktkey, char prefix_byte,
+                                  krb5_boolean pac_expected);
 
 static void
 check(krb5_error_code code)
@@ -206,7 +207,7 @@ display_binary_or_ascii(krb5_authdata *ad)
  * must be the ticket session key. */
 static void
 display_authdata(krb5_authdata *ad, krb5_keyblock *skey, krb5_keyblock *tktkey,
-                 int prefix_byte)
+                 int prefix_byte, krb5_boolean pac_expected)
 {
     krb5_authdata **inner_ad;
 
@@ -214,13 +215,18 @@ display_authdata(krb5_authdata *ad, krb5_keyblock *skey, krb5_keyblock *tktkey,
         ad->ad_type == KRB5_AUTHDATA_MANDATORY_FOR_KDC ||
         ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED ||
         ad->ad_type == KRB5_AUTHDATA_CAMMAC) {
+        if (ad->ad_type != KRB5_AUTHDATA_IF_RELEVANT)
+            pac_expected = FALSE;
         /* Decode and display the contents. */
         inner_ad = get_container_contents(ad, skey, tktkey);
-        display_authdata_list(inner_ad, skey, tktkey, get_prefix_byte(ad));
+        display_authdata_list(inner_ad, skey, tktkey, get_prefix_byte(ad),
+                              pac_expected);
         krb5_free_authdata(ctx, inner_ad);
         return;
     }
 
+    assert(!pac_expected || ad->ad_type == KRB5_AUTHDATA_WIN2K_PAC);
+
     printf("%c", prefix_byte);
     printf("%d: ", (int)ad->ad_type);
 
@@ -233,12 +239,43 @@ display_authdata(krb5_authdata *ad, krb5_keyblock *skey, krb5_keyblock *tktkey,
 
 static void
 display_authdata_list(krb5_authdata **list, krb5_keyblock *skey,
-                      krb5_keyblock *tktkey, char prefix_byte)
+                      krb5_keyblock *tktkey, char prefix_byte,
+                      krb5_boolean pac_expected)
 {
     if (list == NULL)
         return;
-    for (; *list != NULL; list++)
-        display_authdata(*list, skey, tktkey, prefix_byte);
+    /* Only expect a PAC in the first element, if at all. */
+    for (; *list != NULL; list++) {
+        display_authdata(*list, skey, tktkey, prefix_byte, pac_expected);
+        pac_expected = FALSE;
+    }
+}
+
+/* If a PAC is present in enc_part2, verify its service signature with key and
+ * set *has_pac to true. */
+static void
+check_pac(krb5_context context, krb5_enc_tkt_part *enc_part2,
+          const krb5_keyblock *key, krb5_boolean *has_pac)
+{
+    krb5_authdata **authdata;
+    krb5_pac pac;
+
+    *has_pac = FALSE;
+
+    check(krb5_find_authdata(context, enc_part2->authorization_data, NULL,
+                             KRB5_AUTHDATA_WIN2K_PAC, &authdata));
+    if (authdata == NULL)
+        return;
+
+    assert(authdata[1] == NULL);
+    check(krb5_pac_parse(context, authdata[0]->contents, authdata[0]->length,
+                         &pac));
+    krb5_free_authdata(context, authdata);
+
+    check(krb5_pac_verify(context, pac, enc_part2->times.authtime,
+                          enc_part2->client, key, NULL));
+    krb5_pac_free(context, pac);
+    *has_pac = TRUE;
 }
 
 int
@@ -252,6 +289,7 @@ main(int argc, char **argv)
     krb5_ticket *ticket;
     krb5_authdata **req_authdata = NULL, *ad;
     krb5_keytab_entry ktent;
+    krb5_boolean with_pac;
     size_t count;
     int c;
 
@@ -311,8 +349,10 @@ main(int argc, char **argv)
                             ticket->enc_part.enctype, &ktent));
     check(krb5_decrypt_tkt_part(ctx, &ktent.key, ticket));
 
+    check_pac(ctx, ticket->enc_part2, &ktent.key, &with_pac);
     display_authdata_list(ticket->enc_part2->authorization_data,
-                          ticket->enc_part2->session, &ktent.key, ' ');
+                          ticket->enc_part2->session, &ktent.key, ' ',
+                          with_pac);
 
     while (count > 0) {
         free(req_authdata[--count]->contents);


More information about the cvs-krb5 mailing list