aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Boukris <iboukris@gmail.com>2018-10-15 18:33:15 +0300
committerGreg Hudson <ghudson@mit.edu>2018-10-23 16:44:02 -0400
commit0b872730081f01d0d2b6f78675bb5c74604cef62 (patch)
treee6bea7500dc8c5581e68cbfaad1087b1e1186845
parenta7020d32cf4c7692aec1903e7818d779713ecd43 (diff)
downloadkrb5-0b872730081f01d0d2b6f78675bb5c74604cef62.zip
krb5-0b872730081f01d0d2b6f78675bb5c74604cef62.tar.gz
krb5-0b872730081f01d0d2b6f78675bb5c74604cef62.tar.bz2
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@mit.edu: added Windows export entry; adjusted comments and test code; edited commit message] ticket: 8756 (new)
-rw-r--r--doc/appdev/gssapi.rst6
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.c3
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.h5
-rw-r--r--src/lib/gssapi/krb5/import_name.c8
-rw-r--r--src/lib/gssapi/libgssapi_krb5.exports1
-rw-r--r--src/lib/gssapi32.def2
-rw-r--r--src/plugins/kdb/test/kdb_test.c3
-rw-r--r--src/tests/gssapi/Makefile.in1
-rw-r--r--src/tests/gssapi/common.c4
-rw-r--r--src/tests/gssapi/t_imp_name.c44
-rw-r--r--src/tests/gssapi/t_oid.c3
-rwxr-xr-xsrc/tests/gssapi/t_s4u.py26
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@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@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;
}
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@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()