[30534] in CVS-changelog-for-Kerberos-V5

home help back first fref pref prev next nref lref last post

krb5 commit: Verify PAC client name independently of name-type

daemon@ATHENA.MIT.EDU (Greg Hudson)
Tue Jun 11 00:07:12 2019

Date: Tue, 11 Jun 2019 00:07:06 -0400
From: Greg Hudson <ghudson@mit.edu>
Message-ID: <201906110407.x5B476Nc020564@drugstore.mit.edu>
To: <cvs-krb5@mit.edu>
MIME-Version: 1.0
Reply-To: krbdev@mit.edu
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: cvs-krb5-bounces@mit.edu

https://github.com/krb5/krb5/commit/e935913a4dc9461c129e373bfd752e8a6c795e28
commit e935913a4dc9461c129e373bfd752e8a6c795e28
Author: Isaac Boukris <iboukris@gmail.com>
Date:   Mon Jun 10 15:33:06 2019 +0300

    Verify PAC client name independently of name-type
    
    In krb5_pac_verify(), unparse the provided principal name and compare
    using strcmp(), instead of parsing pac principal, in order to avoid
    relying on the provided name type.
    
    This change is needed for tickets issued with cross-realm S4U2Proxy
    (with resource-based constrained delegation), because the final
    request uses a cross-TGT as the evidence ticket, so the ticket client
    name is taken from the PAC and does not preserve the name type.
    Microsoft KDCs use NT-MS-PRINCIPAL as the ticket client name type in
    this case, regardless of the original name type.
    
    [ghudson@mit.edu: rewrote commit message; made minor style edits]
    
    ticket: 8815 (new)

 src/lib/krb5/krb/pac.c   |   29 +++++++-------------------
 src/lib/krb5/krb/t_pac.c |   49 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 56 insertions(+), 22 deletions(-)

diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
index cc74f37..5efc91e 100644
--- a/src/lib/krb5/krb/pac.c
+++ b/src/lib/krb5/krb/pac.c
@@ -408,12 +408,11 @@ k5_pac_validate_client(krb5_context context,
 {
     krb5_error_code ret;
     krb5_data client_info;
-    char *pac_princname;
+    char *pac_princname, *princname;
     unsigned char *p;
     krb5_timestamp pac_authtime;
     krb5_ui_2 pac_princname_length;
     int64_t pac_nt_authtime;
-    krb5_principal pac_principal;
     int flags = 0;
 
     ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_CLIENT_INFO,
@@ -442,33 +441,21 @@ k5_pac_validate_client(krb5_context context,
     if (ret != 0)
         return ret;
 
-    /* Parse the UTF-8 name as an enterprise principal if we are matching
-     * against one; otherwise parse it as a regular principal. */
-    if (principal->type == KRB5_NT_ENTERPRISE_PRINCIPAL)
-        flags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE;
+    flags = KRB5_PRINCIPAL_UNPARSE_DISPLAY;
+    if (!with_realm)
+        flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM;
 
-    if (with_realm)
-        flags |= KRB5_PRINCIPAL_PARSE_REQUIRE_REALM;
-    else
-        flags |= KRB5_PRINCIPAL_PARSE_NO_REALM;
-
-    ret = krb5_parse_name_flags(context, pac_princname, flags, &pac_principal);
+    ret = krb5_unparse_name_flags(context, principal, flags, &princname);
     if (ret != 0) {
         free(pac_princname);
         return ret;
     }
 
-    free(pac_princname);
-
-    if (pac_authtime != authtime ||
-        !krb5_principal_compare_flags(context,
-                                      pac_principal,
-                                      principal,
-                                      with_realm ? 0 :
-                                      KRB5_PRINCIPAL_COMPARE_IGNORE_REALM))
+    if (pac_authtime != authtime || strcmp(pac_princname, princname) != 0)
         ret = KRB5KRB_AP_WRONG_PRINC;
 
-    krb5_free_principal(context, pac_principal);
+    free(pac_princname);
+    krb5_free_unparsed_name(context, princname);
 
     return ret;
 }
diff --git a/src/lib/krb5/krb/t_pac.c b/src/lib/krb5/krb/t_pac.c
index 7b756a2..ee47152 100644
--- a/src/lib/krb5/krb/t_pac.c
+++ b/src/lib/krb5/krb/t_pac.c
@@ -733,13 +733,18 @@ main(int argc, char **argv)
     }
 
     {
-        krb5_principal ep;
+        krb5_principal ep, np;
 
         ret = krb5_parse_name_flags(context, user,
                                     KRB5_PRINCIPAL_PARSE_ENTERPRISE, &ep);
         if (ret)
             err(context, ret, "krb5_parse_name_flags");
 
+        ret = krb5_copy_principal(context, ep, &np);
+        if (ret)
+            err(context, ret, "krb5_copy_principal");
+        np->type = KRB5_NT_MS_PRINCIPAL;
+
         /* Try to verify as enterprise. */
         ret = krb5_pac_verify(context, pac, authtime, ep, &member_keyblock,
                               &kdc_keyblock);
@@ -788,6 +793,47 @@ main(int argc, char **argv)
         if (ret)
             err(context, ret, "krb5_pac_verify enterprise failed");
 
+        /* Also verify enterprise as KRB5_NT_MS_PRINCIPAL. */
+        ret = krb5_pac_verify(context, pac, authtime, np, &member_keyblock,
+                              &kdc_keyblock);
+        if (ret)
+            err(context, ret, "krb5_pac_verify enterprise as nt-ms failed");
+
+        ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock,
+                              &kdc_keyblock);
+        if (!ret)
+            err(context, ret, "krb5_pac_verify should have failed");
+
+        krb5_pac_free(context, pac);
+
+        /* Test nt-ms-principal. */
+        ret = krb5_pac_init(context, &pac);
+        if (ret)
+            err(context, ret, "krb5_pac_init");
+
+        ret = krb5_pac_sign(context, pac, authtime, np, &member_keyblock,
+                            &kdc_keyblock, &data);
+        if (ret)
+            err(context, ret, "krb5_pac_sign enterprise failed");
+
+        krb5_pac_free(context, pac);
+
+        ret = krb5_pac_parse(context, data.data, data.length, &pac);
+        krb5_free_data_contents(context, &data);
+        if (ret)
+            err(context, ret, "krb5_pac_parse failed");
+
+        ret = krb5_pac_verify(context, pac, authtime, np, &member_keyblock,
+                              &kdc_keyblock);
+        if (ret)
+            err(context, ret, "krb5_pac_verify enterprise failed");
+
+        /* Also verify as enterprise principal. */
+        ret = krb5_pac_verify(context, pac, authtime, ep, &member_keyblock,
+                              &kdc_keyblock);
+        if (ret)
+            err(context, ret, "krb5_pac_verify nt-ms as enterprise failed");
+
         ret = krb5_pac_verify(context, pac, authtime, p, &member_keyblock,
                               &kdc_keyblock);
         if (!ret)
@@ -862,6 +908,7 @@ main(int argc, char **argv)
             err(context, ret, "krb5_pac_verify_ext should have failed");
 
         krb5_free_principal(context, ep);
+        krb5_free_principal(context, np);
     }
 
     krb5_pac_free(context, pac);
_______________________________________________
cvs-krb5 mailing list
cvs-krb5@mit.edu
https://mailman.mit.edu/mailman/listinfo/cvs-krb5

home help back first fref pref prev next nref lref last post