krb5 commit: Add GSS_KRB5_NT_ENTERPRISE_NAME name type

Greg Hudson ghudson at mit.edu
Tue Oct 23 17:40:12 EDT 2018


https://github.com/krb5/krb5/commit/0b872730081f01d0d2b6f78675bb5c74604cef62
commit 0b872730081f01d0d2b6f78675bb5c74604cef62
Author: Isaac Boukris <iboukris at gmail.com>
Date:   Mon Oct 15 18:33:15 2018 +0300

    Add GSS_KRB5_NT_ENTERPRISE_NAME name type
    
    Add a new name-type OID which causes a string to be imported as an
    enterprise name.  This is useful for authenticating and impersonating
    users with their UPN names.
    
    Resurrect t_imp_name test to exercise importing of the new name OID.
    Also add a test using the new name in cross-realm protocol transition,
    to exercise s4u_identify_user() with multiple realms.
    
    [ghudson at mit.edu: added Windows export entry; adjusted comments and
    test code; edited commit message]
    
    ticket: 8756 (new)

 doc/appdev/gssapi.rst                 |    6 ++++
 src/lib/gssapi/krb5/gssapi_krb5.c     |    3 ++
 src/lib/gssapi/krb5/gssapi_krb5.h     |    5 +++
 src/lib/gssapi/krb5/import_name.c     |    8 ++++-
 src/lib/gssapi/libgssapi_krb5.exports |    1 +
 src/lib/gssapi32.def                  |    2 +
 src/plugins/kdb/test/kdb_test.c       |    3 +-
 src/tests/gssapi/Makefile.in          |    1 +
 src/tests/gssapi/common.c             |    4 ++-
 src/tests/gssapi/t_imp_name.c         |   44 +++++++++++++++++++++++++++++---
 src/tests/gssapi/t_oid.c              |    3 ++
 src/tests/gssapi/t_s4u.py             |   26 +++++++++++++++++--
 12 files changed, 94 insertions(+), 12 deletions(-)

diff --git a/doc/appdev/gssapi.rst b/doc/appdev/gssapi.rst
index a53094f..d26ac08 100644
--- a/doc/appdev/gssapi.rst
+++ b/doc/appdev/gssapi.rst
@@ -55,6 +55,12 @@ name types are supported by the krb5 mechanism:
 * **GSS_C_NT_EXPORT_NAME**: The value must be the result of a
   gss_export_name_ call.
 
+* **GSS_KRB5_NT_ENTERPRISE_NAME**: The value should be a krb5
+  enterprise name string (see :rfc:`6806` section 5), in the form
+  ``user at suffix``.  This name type is used to convey alias names, and
+  is defined in the ``<gssapi/gssapi_krb5.h>`` header.  (New in
+  release 1.17.)
+
 
 Initiator credentials
 ---------------------
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index 1eaf2bf..79b83e0 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -152,6 +152,8 @@ const gss_OID_desc krb5_gss_oid_array[] = {
     {NO_CI_FLAGS_X_OID_LENGTH, NO_CI_FLAGS_X_OID},
     /* this is an inquire cred OID */
     {GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID},
+    /* GSS_KRB5_NT_ENTERPRISE_NAME */
+    {10, "\052\206\110\206\367\022\001\002\002\006"},
     { 0, 0 }
 };
 
@@ -169,6 +171,7 @@ const gss_OID GSS_KRB5_NT_PRINCIPAL_NAME        = &kg_oids[5];
 
 const gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X       = &kg_oids[7];
 const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR    = &kg_oids[8];
+const gss_OID GSS_KRB5_NT_ENTERPRISE_NAME       = &kg_oids[9];
 
 static const gss_OID_set_desc oidsets[] = {
     {1, &kg_oids[0]}, /* RFC OID */
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.h b/src/lib/gssapi/krb5/gssapi_krb5.h
index e145eec..84b4159 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.h
+++ b/src/lib/gssapi/krb5/gssapi_krb5.h
@@ -73,6 +73,11 @@ GSS_DLLIMP extern const gss_OID GSS_KRB5_NT_PRINCIPAL_NAME;
  * generic(1) string_uid_name(3)}.  The recommended symbolic name for
  * this type is "GSS_KRB5_NT_STRING_UID_NAME". */
 
+/* Kerberos Enterprise Name Form (see RFC 6806 section 5): */
+GSS_DLLIMP extern const gss_OID GSS_KRB5_NT_ENTERPRISE_NAME;
+/* {iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
+ * krb5(2) krb5-enterprise-name(6)}. */
+
 GSS_DLLIMP extern const gss_OID gss_mech_krb5;
 GSS_DLLIMP extern const gss_OID gss_mech_krb5_old;
 GSS_DLLIMP extern const gss_OID gss_mech_krb5_wrong;
diff --git a/src/lib/gssapi/krb5/import_name.c b/src/lib/gssapi/krb5/import_name.c
index 3f5492b..da2ab14 100644
--- a/src/lib/gssapi/krb5/import_name.c
+++ b/src/lib/gssapi/krb5/import_name.c
@@ -140,6 +140,7 @@ krb5_gss_import_name(minor_status, input_name_buffer,
     krb5_authdata_context ad_context = NULL;
     OM_uint32 status = GSS_S_FAILURE;
     krb5_gss_name_t name;
+    int flags = 0;
 
     *output_name = NULL;
     *minor_status = 0;
@@ -206,7 +207,10 @@ krb5_gss_import_name(minor_status, input_name_buffer,
         if ((input_name_type == GSS_C_NULL_OID) ||
             g_OID_equal(input_name_type, gss_nt_krb5_name) ||
             g_OID_equal(input_name_type, gss_nt_user_name)) {
-            stringrep = (char *) tmp;
+            stringrep = tmp;
+        } else if (g_OID_equal(input_name_type, GSS_KRB5_NT_ENTERPRISE_NAME)) {
+            stringrep = tmp;
+            flags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE;
 #ifndef NO_PASSWORD
         } else if (g_OID_equal(input_name_type, gss_nt_machine_uid_name)) {
             uid = *(uid_t *) input_name_buffer->value;
@@ -296,7 +300,7 @@ krb5_gss_import_name(minor_status, input_name_buffer,
 
         /* At this point, stringrep is set, or if not, code is. */
         if (stringrep) {
-            code = krb5_parse_name(context, (char *)stringrep, &princ);
+            code = krb5_parse_name_flags(context, stringrep, flags, &princ);
             if (code)
                 goto cleanup;
         } else {
diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports
index b07f69f..c292cb1 100644
--- a/src/lib/gssapi/libgssapi_krb5.exports
+++ b/src/lib/gssapi/libgssapi_krb5.exports
@@ -9,6 +9,7 @@ GSS_C_NT_MACHINE_UID_NAME
 GSS_C_NT_STRING_UID_NAME
 GSS_C_NT_USER_NAME
 GSS_KRB5_NT_PRINCIPAL_NAME
+GSS_KRB5_NT_ENTERPRISE_NAME
 GSS_KRB5_CRED_NO_CI_FLAGS_X
 GSS_KRB5_GET_CRED_IMPERSONATOR
 GSS_C_MA_MECH_CONCRETE
diff --git a/src/lib/gssapi32.def b/src/lib/gssapi32.def
index 842f3d5..e6b1479 100644
--- a/src/lib/gssapi32.def
+++ b/src/lib/gssapi32.def
@@ -185,3 +185,5 @@ EXPORTS
 ; Added in 1.16
 	GSS_KRB5_GET_CRED_IMPERSONATOR			@148	DATA
 	GSS_C_SEC_CONTEXT_SASL_SSF			@149	DATA
+; Added in 1.17
+	GSS_KRB5_NT_ENTERPRISE_NAME			@150 	DATA
diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c
index bc65bfb..6df2d58 100644
--- a/src/plugins/kdb/test/kdb_test.c
+++ b/src/plugins/kdb/test/kdb_test.c
@@ -334,7 +334,8 @@ test_get_principal(krb5_context context, krb5_const_principal search_for,
                                   &search_name));
     canon = get_string(h, "alias", search_name, NULL);
     if (canon != NULL) {
-        if (!(flags & KRB5_KDB_FLAG_ALIAS_OK)) {
+        if (!(flags & KRB5_KDB_FLAG_ALIAS_OK) &&
+            search_for->type != KRB5_NT_ENTERPRISE_PRINCIPAL) {
             ret = KRB5_KDB_NOENTRY;
             goto cleanup;
         }
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
index 2463c23..a7b8da4 100644
--- a/src/tests/gssapi/Makefile.in
+++ b/src/tests/gssapi/Makefile.in
@@ -40,6 +40,7 @@ check-unix: t_oid
 	$(RUN_TEST) ./t_invalid
 	$(RUN_TEST) ./t_oid
 	$(RUN_TEST) ./t_prf
+	$(RUN_TEST) ./t_imp_name
 
 check-pytests: ccinit ccrefresh t_accname t_add_cred t_ccselect t_ciflags \
 	t_credstore t_enctypes t_err t_export_cred t_export_name t_imp_cred \
diff --git a/src/tests/gssapi/common.c b/src/tests/gssapi/common.c
index 0de36d3..83e9d9b 100644
--- a/src/tests/gssapi/common.c
+++ b/src/tests/gssapi/common.c
@@ -97,10 +97,12 @@ import_name(const char *str)
         nametype = GSS_C_NT_USER_NAME;
     else if (*str == 'p')
         nametype = (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME;
+    else if (*str == 'e')
+        nametype = (gss_OID)GSS_KRB5_NT_ENTERPRISE_NAME;
     else if (*str == 'h')
         nametype = GSS_C_NT_HOSTBASED_SERVICE;
     if (nametype == NULL || str[1] != ':')
-        errout("names must begin with u: or p: or h:");
+        errout("names must begin with u: or p: or e: or h:");
     buf.value = (char *)str + 2;
     buf.length = strlen(str) - 2;
     major = gss_import_name(&minor, &buf, nametype, &name);
diff --git a/src/tests/gssapi/t_imp_name.c b/src/tests/gssapi/t_imp_name.c
index 4fcd61b..3d73dc8 100644
--- a/src/tests/gssapi/t_imp_name.c
+++ b/src/tests/gssapi/t_imp_name.c
@@ -29,13 +29,37 @@
  */
 
 #include <stdio.h>
+#include <string.h>
 
 #include "common.h"
 
-int
-main(int argc, char **argv)
+static const char *
+oid_str(char type)
+{
+    switch (type) {
+    case 'p': /* GSS_KRB5_NT_PRINCIPAL_NAME */
+        return "{ 1 2 840 113554 1 2 2 1 }";
+    case 'e': /* GSS_KRB5_NT_ENTERPRISE_NAME */
+        return "{ 1 2 840 113554 1 2 2 6 }";
+    case 'h': /* GSS_C_NT_HOSTBASED_SERVICE */
+        return "{ 1 2 840 113554 1 2 1 4 }";
+    }
+    return "no_oid";
+}
+
+/* Return true if buf has the same contents as str, plus a zero byte if
+ * indicated by buf_includes_nullterm. */
+static int
+buf_eq_str(gss_buffer_t buf, const char *str, int buf_includes_nullterm)
+{
+    size_t len = strlen(str) + (buf_includes_nullterm ? 1 : 0);
+
+    return (buf->length == len && memcmp(buf->value, str, len) == 0);
+}
+
+static void
+test_import_name(const char *name)
 {
-    const char *name = "host at dcl.mit.edu";
     OM_uint32 major, minor;
     gss_name_t gss_name;
     gss_buffer_desc buf;
@@ -45,14 +69,24 @@ main(int argc, char **argv)
 
     major = gss_display_name(&minor, gss_name, &buf, &name_oid);
     check_gsserr("gss_display_name", major, minor);
-    printf("name is: %.*s\n", (int)buf.length, (char *)buf.value);
+    if (!buf_eq_str(&buf, name + 2, 0))
+        errout("wrong name string");
     (void)gss_release_buffer(&minor, &buf);
 
     major = gss_oid_to_str(&minor, name_oid, &buf);
     check_gsserr("gss_oid_to_str", major, minor);
-    printf("name type is: %.*s\n", (int)buf.length, (char *)buf.value);
+    if (!buf_eq_str(&buf, oid_str(*name), 1))
+        errout("wrong name type");
     (void)gss_release_buffer(&minor, &buf);
     (void)gss_release_name(&minor, &gss_name);
+}
+
+int
+main(int argc, char **argv)
+{
+    test_import_name("p:user at MIT.EDU");
+    test_import_name("e:enterprise at mit.edu@MIT.EDU");
+    test_import_name("h:HOST at dc1.mit.edu");
 
     return 0;
 }
diff --git a/src/tests/gssapi/t_oid.c b/src/tests/gssapi/t_oid.c
index 417f7b9..1c9d394 100644
--- a/src/tests/gssapi/t_oid.c
+++ b/src/tests/gssapi/t_oid.c
@@ -59,6 +59,9 @@ static struct {
     /* GSS_KRB5_NT_PRINCIPAL_NAME */
     { "{ 1 2 840 113554 1 2 2 1 }", " {01 2 840 113554 1 2 2 1  } ",
       { 10, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x01" } },
+    /* GSS_KRB5_NT_ENTERPRISE_NAME */
+    { "{ 1 2 840 113554 1 2 2 6 }", " {1.2.840.113554.1.2.2.6} ",
+      { 10, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x06" } },
     /* gss_krb5_nt_principal */
     { "{ 1 2 840 113554 1 2 2 2 }", "{1.2.840.113554.1.2.2.2}",
       { 10, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x02" } },
diff --git a/src/tests/gssapi/t_s4u.py b/src/tests/gssapi/t_s4u.py
index eb9545d..fd29e1a 100755
--- a/src/tests/gssapi/t_s4u.py
+++ b/src/tests/gssapi/t_s4u.py
@@ -143,14 +143,16 @@ realm.stop()
 mark('cross-realm S4U2Self')
 testprincs = {'krbtgt/SREALM': {'keys': 'aes128-cts'},
               'krbtgt/UREALM': {'keys': 'aes128-cts'},
-              'user': {'keys': 'aes128-cts'}}
+              'user': {'keys': 'aes128-cts', 'flags': '+preauth'}}
 kdcconf1 = {'realms': {'$realm': {'database_module': 'test'}},
             'dbmodules': {'test': {'db_library': 'test',
-                                   'princs': testprincs }}}
+                                   'princs': testprincs,
+                                   'alias': {'enterprise at abc': '@UREALM'}}}}
 kdcconf2 = {'realms': {'$realm': {'database_module': 'test'}},
             'dbmodules': {'test': {'db_library': 'test',
                                    'princs': testprincs,
-                                   'alias': {'user at SREALM': '@SREALM'}}}}
+                                   'alias': {'user at SREALM': '@SREALM',
+                                             'enterprise at abc': 'user'}}}}
 r1, r2 = cross_realms(2, xtgts=(),
                       args=({'realm': 'SREALM', 'kdc_conf': kdcconf1},
                             {'realm': 'UREALM', 'kdc_conf': kdcconf2}),
@@ -175,6 +177,24 @@ msgs = ('Getting credentials user at UREALM -> user at SREALM',
 r1.run(['./t_s4u', 'p:' + r2.user_princ, '-', r1.keytab], env=no_default,
        expected_trace=msgs)
 
+# Test realm identification of enterprise principal names ([MS-S4U]
+# 3.1.5.1.1.1).  Attach a bogus realm to the enterprise name to verify
+# that we start at the server realm.
+mark('cross-realm S4U2Self with enterprise name')
+msgs = ('Getting initial credentials for enterprise\\@abc at SREALM',
+        'Processing preauth types: PA-FOR-X509-USER (130)',
+        'Sending unauthenticated request',
+        '/Realm not local to KDC',
+        'Following referral to realm UREALM',
+        'Processing preauth types: PA-FOR-X509-USER (130)',
+        'Sending unauthenticated request',
+        '/Additional pre-authentication required',
+        '/Generic preauthentication failure',
+        'Getting credentials enterprise\\@abc at UREALM -> user at SREALM',
+        'TGS reply is for enterprise\@abc at UREALM -> user at SREALM')
+r1.run(['./t_s4u', 'e:enterprise at abc@NOREALM', '-', r1.keytab],
+       expected_trace=msgs)
+
 r1.stop()
 r2.stop()
 


More information about the cvs-krb5 mailing list