]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add GSS_KRB5_NT_ENTERPRISE_NAME name type 857/head
authorIsaac Boukris <iboukris@gmail.com>
Mon, 15 Oct 2018 15:33:15 +0000 (18:33 +0300)
committerGreg Hudson <ghudson@mit.edu>
Tue, 23 Oct 2018 20:44:02 +0000 (16:44 -0400)
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@mit.edu: added Windows export entry; adjusted comments and
test code; edited commit message]

ticket: 8756 (new)

12 files changed:
doc/appdev/gssapi.rst
src/lib/gssapi/krb5/gssapi_krb5.c
src/lib/gssapi/krb5/gssapi_krb5.h
src/lib/gssapi/krb5/import_name.c
src/lib/gssapi/libgssapi_krb5.exports
src/lib/gssapi32.def
src/plugins/kdb/test/kdb_test.c
src/tests/gssapi/Makefile.in
src/tests/gssapi/common.c
src/tests/gssapi/t_imp_name.c
src/tests/gssapi/t_oid.c
src/tests/gssapi/t_s4u.py

index a53094fa12eb121eb8afffa9447d31aca3537cdd..d26ac0825bb1192e4c43249691eae2b28b72dea5 100644 (file)
@@ -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@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
 ---------------------
index 1eaf2bffbf657bc52d40ee3927c039b3d6d0af31..79b83e0c6b6550607157ca16914b7af8e8094880 100644 (file)
@@ -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 */
index e145eec3b44ce1604f9d358acc1f497fafc097bc..84b415920a912d161e846e9f21b66e94a4cb47f7 100644 (file)
@@ -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;
index 3f5492b99f6b20845fb951cfa2a4b30e6b4c30b3..da2ab1423217d289418c223e30fec73a1a3eeac8 100644 (file)
@@ -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 {
index b07f69fd157292d6881f2d173a50c69ac800e4ae..c292cb1af935810394f6aff2692672bacb3520ea 100644 (file)
@@ -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
index 842f3d52f3cdbcf034638824be74edf46573e912..e6b1479bbb9fec628adea1b4340bd79df26e5cf9 100644 (file)
@@ -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
index bc65bfb1bc44dc55f20ba9b5f075807078a3791d..6df2d588f1675574f39f74d04f1e2adf0e9e49c7 100644 (file)
@@ -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;
         }
index 2463c23c77f3ffc50a91802471c3fc15201cfa3f..a7b8da4d62f4374105f659b637babad219e8d1c9 100644 (file)
@@ -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 \
index 0de36d3135ce3db2451075d976888866010e3289..83e9d9bb8e913015db1aef81569470aba043488f 100644 (file)
@@ -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);
index 4fcd61b50f20de0632eaebbd58dd640395cac417..3d73dc8fbc8b9df5e37e60c033b3c5f33b9ce836 100644 (file)
  */
 
 #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@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@MIT.EDU");
+    test_import_name("e:enterprise@mit.edu@MIT.EDU");
+    test_import_name("h:HOST@dc1.mit.edu");
 
     return 0;
 }
index 417f7b9c6a029a0147abfc7eb29d059004281a32..1c9d394167bd600dc270ec4467ae0fee8b6b7921 100644 (file)
@@ -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" } },
index eb9545ddfbfc74b899b5f43942437e1cf40f6090..fd29e1a270a763ec76776ec023854dd4829637ba 100755 (executable)
@@ -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@abc': '@UREALM'}}}}
 kdcconf2 = {'realms': {'$realm': {'database_module': 'test'}},
             'dbmodules': {'test': {'db_library': 'test',
                                    'princs': testprincs,
-                                   'alias': {'user@SREALM': '@SREALM'}}}}
+                                   'alias': {'user@SREALM': '@SREALM',
+                                             'enterprise@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@UREALM -> user@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@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@UREALM -> user@SREALM',
+        'TGS reply is for enterprise\@abc@UREALM -> user@SREALM')
+r1.run(['./t_s4u', 'e:enterprise@abc@NOREALM', '-', r1.keytab],
+       expected_trace=msgs)
+
 r1.stop()
 r2.stop()