spnego: Also use mechglue names
authorNicolas Williams <nico@twosigma.com>
Sat, 25 Apr 2020 00:04:50 +0000 (19:04 -0500)
committerNicolas Williams <nico@twosigma.com>
Sun, 26 Apr 2020 02:22:32 +0000 (21:22 -0500)
14 files changed:
lib/gssapi/gssapi_mech.h
lib/gssapi/mech/gss_accept_sec_context.c
lib/gssapi/mech/gss_canonicalize_name.c
lib/gssapi/mech/gss_import_name.c
lib/gssapi/mech/gss_init_sec_context.c
lib/gssapi/mech/gss_inquire_context.c
lib/gssapi/mech/gss_names.c
lib/gssapi/spnego/context_stubs.c
lib/gssapi/spnego/external.c
lib/gssapi/test_context.c
tests/gss/check-context.in
tests/gss/krb5.conf.in
tests/kdc/an2ln-db.txt
tests/kdc/k5login/mapped_user1 [new file with mode: 0644]

index fa027f805a2f2036337fedf9af819fd33965e424..07682ca7f7dc12b754d1b3230360e4079a133160 100644 (file)
@@ -553,6 +553,7 @@ struct gss_mech_compat_desc_struct;
 
 /* gm_flags */
 #define GM_USE_MG_CRED         1       /* uses mech glue credentials */
+#define GM_USE_MG_NAME         2       /* uses mech glue names       */
 
 typedef struct gssapi_mech_interface_desc {
        unsigned                        gm_version;
index 8a5b5021e7a96877ef5a19a5a927d0d58e2903fd..6dd8fa98550fdfe301596cfdaf3fe3d9e587a69c 100644 (file)
@@ -182,12 +182,11 @@ gss_accept_sec_context(OM_uint32 *minor_status,
                  * and we have to try all mechs (that we have a cred element
                  * for, if we have a cred).
                  */
-               ctx = malloc(sizeof(struct _gss_context));
+               ctx = calloc(1, sizeof(struct _gss_context));
                if (!ctx) {
                        *minor_status = ENOMEM;
                        return (GSS_S_DEFECTIVE_TOKEN);
                }
-               memset(ctx, 0, sizeof(struct _gss_context));
                 if (mech_oid != GSS_C_NO_OID) {
                         m = ctx->gc_mech = __gss_get_mechanism(mech_oid);
                         if (!m) {
@@ -334,11 +333,18 @@ got_one:
        }
 
        if (mech_type)
-           *mech_type = mech_ret_type;
+               *mech_type = mech_ret_type;
 
-       if (src_name && src_mn) {
+       if (src_name && src_mn && (ctx->gc_mech->gm_flags & GM_USE_MG_NAME)) {
+               /* Negotiation mechanisms use mechglue names as names */
+               *src_name = src_mn;
+               src_mn = GSS_C_NO_NAME;
+       } else if (src_name && src_mn) {
                /*
                 * Make a new name and mark it as an MN.
+                *
+                * Note that _gss_create_name() consumes `src_mn' but doesn't
+                * take a pointer, so it can't set it to GSS_C_NO_NAME.
                 */
                struct _gss_name *name = _gss_create_name(src_mn, m);
 
@@ -348,6 +354,7 @@ got_one:
                        return (GSS_S_FAILURE);
                }
                *src_name = (gss_name_t) name;
+               src_mn = GSS_C_NO_NAME;
        } else if (src_mn) {
                m->gm_release_name(minor_status, &src_mn);
        }
index 8ffeec78f1fdb1596c42c6a64812a04d9adca379..859c6880eb237ee6960487c95972c5dbde40827d 100644 (file)
@@ -67,7 +67,11 @@ gss_canonicalize_name(OM_uint32 *minor_status,
        gss_name_t new_canonical_name;
 
        *minor_status = 0;
-       *output_name = 0;
+       *output_name = GSS_C_NO_NAME;
+
+       if ((m = __gss_get_mechanism(mech_type)) == NULL ||
+            (m->gm_flags & GM_USE_MG_NAME))
+               return GSS_S_BAD_MECH;
 
        major_status = _gss_find_mn(minor_status, name, mech_type, &mn);
        if (major_status)
index d268b5e4536f874c57f5a435cd0a6beb18ffb020..d7559981dc532e8830e0c820b6f930641da29947 100644 (file)
@@ -120,7 +120,7 @@ _gss_import_export_name(OM_uint32 *minor_status,
                return (GSS_S_BAD_NAME);
 
        m = __gss_get_mechanism(&mech_oid);
-       if (!m)
+       if (!m || !m->gm_import_name)
                return (GSS_S_BAD_MECH);
 
        /*
@@ -242,6 +242,9 @@ gss_import_name(OM_uint32 *minor_status,
        HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
                int present = 0;
 
+                if ((m->gm_mech.gm_flags & GM_USE_MG_NAME))
+                    continue;
+
                major_status = gss_test_oid_set_member(minor_status,
                    name_type, m->gm_name_types, &present);
 
index 250eafef251530b19ac5ca58b63d2db8db8fd65d..6d28938ce3716b64d0363bdf4c88676b14adbf7a 100644 (file)
@@ -158,6 +158,7 @@ gss_init_sec_context(OM_uint32 * minor_status,
 {
        OM_uint32 major_status;
        gssapi_mech_interface m;
+        gss_const_name_t mn_inner = GSS_C_NO_NAME;
        struct _gss_name *name = (struct _gss_name *) target_name;
        struct _gss_mechanism_name *mn;
        struct _gss_context *ctx = (struct _gss_context *) *context_handle;
@@ -216,12 +217,18 @@ gss_init_sec_context(OM_uint32 * minor_status,
        /*
         * Find the MN for this mechanism.
         */
-       major_status = _gss_find_mn(minor_status, name, mech_type, &mn);
-       if (major_status != GSS_S_COMPLETE) {
-               if (allocated_ctx)
-                    free(ctx);
-               return major_status;
-       }
+        if ((m->gm_flags & GM_USE_MG_NAME)) {
+            mn_inner = target_name;
+        } else {
+            major_status = _gss_find_mn(minor_status, name, mech_type, &mn);
+            if (major_status != GSS_S_COMPLETE) {
+                    if (allocated_ctx)
+                        free(ctx);
+                    return major_status;
+            }
+            if (mn)
+                mn_inner = mn->gmn_name;
+        }
 
        /*
         * If we have a cred, find the cred for this mechanism.
@@ -246,7 +253,7 @@ gss_init_sec_context(OM_uint32 * minor_status,
        major_status = m->gm_init_sec_context(minor_status,
            cred_handle,
            &ctx->gc_ctx,
-           mn ? mn->gmn_name : GSS_C_NO_NAME,
+           mn_inner,
            mech_type,
            req_flags,
            time_req,
index e7466a461d9eb86ddf961676b0c6a0e2156ff5e2..61406968822712aa41c1a1d74437cede1deedbfd 100644 (file)
@@ -82,7 +82,11 @@ gss_inquire_context(OM_uint32 *minor_status,
                return (major_status);
        }
 
-       if (src_name) {
+       if (src_name && (m->gm_flags & GM_USE_MG_NAME)) {
+               *src_name = src_mn;
+               src_mn = GSS_C_NO_NAME;
+       } else if (src_name && src_mn) {
+               /* _gss_create_name() consumes `src_mn' on success */
                name = _gss_create_name(src_mn, m);
                if (!name) {
                        if (mech_type)
@@ -92,9 +96,12 @@ gss_inquire_context(OM_uint32 *minor_status,
                        return (GSS_S_FAILURE);
                }
                *src_name = (gss_name_t) name;
+               src_mn = GSS_C_NO_NAME;
        }
 
-       if (targ_name) {
+       if (targ_name && (m->gm_flags & GM_USE_MG_NAME)) {
+               *targ_name = targ_mn;
+       } else if (targ_name && targ_mn) {
                name = _gss_create_name(targ_mn, m);
                if (!name) {
                        if (mech_type)
@@ -106,6 +113,7 @@ gss_inquire_context(OM_uint32 *minor_status,
                        return (GSS_S_FAILURE);
                }
                *targ_name = (gss_name_t) name;
+               targ_mn = GSS_C_NO_NAME;
        }
 
        return (GSS_S_COMPLETE);
index b39c2761ddfde0c89c602ca903342b1a4a625662..729e7f2ad7dbaacbfd02fa5bad95bf10407f672e 100644 (file)
@@ -74,7 +74,7 @@ _gss_find_mn(OM_uint32 *minor_status,
                        return GSS_S_BAD_NAME;
 
                m = __gss_get_mechanism(mech);
-               if (!m)
+               if (!m || !m->gm_import_name)
                        return (GSS_S_BAD_MECH);
 
                mn = malloc(sizeof(struct _gss_mechanism_name));
index 88f37adcd22232e0266895a82bb199b38fe660c0..27e4bfb7e84af52accbdff9b70935e64967d83d3 100644 (file)
@@ -228,55 +228,6 @@ OM_uint32 GSSAPI_CALLCONV _gss_spnego_unwrap
                      qop_state);
 }
 
-OM_uint32 GSSAPI_CALLCONV _gss_spnego_compare_name
-           (OM_uint32 *minor_status,
-            gss_const_name_t name1,
-            gss_const_name_t name2,
-            int * name_equal
-           )
-{
-    return gss_compare_name(minor_status, name1, name2, name_equal);
-}
-
-OM_uint32 GSSAPI_CALLCONV _gss_spnego_display_name
-           (OM_uint32 * minor_status,
-            gss_const_name_t input_name,
-            gss_buffer_t output_name_buffer,
-            gss_OID * output_name_type
-           )
-{
-    return gss_display_name(minor_status, input_name,
-                           output_name_buffer, output_name_type);
-}
-
-OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_name
-           (OM_uint32 * minor_status,
-            const gss_buffer_t name_buffer,
-            const gss_OID name_type,
-            gss_name_t * output_name
-           )
-{
-    return gss_import_name(minor_status, name_buffer,
-                          name_type, output_name);
-}
-
-OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_name
-           (OM_uint32  * minor_status,
-            gss_const_name_t input_name,
-            gss_buffer_t exported_name
-           )
-{
-    return gss_export_name(minor_status, input_name, exported_name);
-}
-
-OM_uint32 GSSAPI_CALLCONV _gss_spnego_release_name
-           (OM_uint32 * minor_status,
-            gss_name_t * input_name
-           )
-{
-    return gss_release_name(minor_status, input_name);
-}
-
 OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_context (
             OM_uint32 * minor_status,
             gss_const_ctx_id_t context_handle,
@@ -469,47 +420,6 @@ out:
     return ret;
 }
 
-OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_mechs_for_name (
-            OM_uint32 * minor_status,
-            gss_const_name_t input_name,
-            gss_OID_set * mech_types
-           )
-{
-    OM_uint32 ret, junk;
-
-    ret = gss_create_empty_oid_set(minor_status, mech_types);
-    if (ret)
-       return ret;
-
-    ret = gss_add_oid_set_member(minor_status,
-                                GSS_SPNEGO_MECHANISM,
-                                mech_types);
-    if (ret)
-       gss_release_oid_set(&junk, mech_types);
-
-    return ret;
-}
-
-OM_uint32 GSSAPI_CALLCONV _gss_spnego_canonicalize_name (
-            OM_uint32 * minor_status,
-            gss_const_name_t input_name,
-            const gss_OID mech_type,
-            gss_name_t * output_name
-           )
-{
-    /* XXX */
-    return gss_duplicate_name(minor_status, input_name, output_name);
-}
-
-OM_uint32 GSSAPI_CALLCONV _gss_spnego_duplicate_name (
-            OM_uint32 * minor_status,
-            gss_const_name_t src_name,
-            gss_name_t * dest_name
-           )
-{
-    return gss_duplicate_name(minor_status, src_name, dest_name);
-}
-
 OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_wrap_iov(OM_uint32 * minor_status,
                     gss_ctx_id_t  context_handle,
index 99b3412d862a1a989803b4d7494a3162b1cde26e..b66f97dabf10d183b5a7cc1674810d213d80127a 100644 (file)
@@ -88,7 +88,7 @@ static gssapi_mech_interface_desc spnego_mech = {
     GMI_VERSION,
     "spnego",
     {6, rk_UNCONST("\x2b\x06\x01\x05\x05\x02") },
-    GM_USE_MG_CRED,
+    GM_USE_MG_CRED | GM_USE_MG_NAME,
     NULL, /* gm_acquire_cred */
     NULL, /* gm_release_cred */
     _gss_spnego_init_sec_context,
@@ -102,11 +102,11 @@ static gssapi_mech_interface_desc spnego_mech = {
     _gss_spnego_unwrap,
     NULL, /* gm_display_status */
     NULL, /* gm_indicate_mechs */
-    _gss_spnego_compare_name,
-    _gss_spnego_display_name,
-    _gss_spnego_import_name,
-    _gss_spnego_export_name,
-    _gss_spnego_release_name,
+    NULL, /* gm_compare_name */
+    NULL, /* gm_display_name */
+    NULL, /* gm_import_name */
+    NULL, /* gm_export_name */
+    NULL, /* gm_release_name */
     NULL, /* gm_inquire_cred */
     _gss_spnego_inquire_context,
     _gss_spnego_wrap_size_limit,
@@ -114,10 +114,10 @@ static gssapi_mech_interface_desc spnego_mech = {
     NULL, /* gm_inquire_cred_by_mech */
     _gss_spnego_export_sec_context,
     _gss_spnego_import_sec_context,
-    NULL /* _gss_spnego_inquire_names_for_mech */,
-    _gss_spnego_inquire_mechs_for_name,
-    _gss_spnego_canonicalize_name,
-    _gss_spnego_duplicate_name,
+    NULL, /* gm_spnego_inquire_names_for_mech */
+    NULL, /* gm_spnego_inquire_mechs_for_name */
+    NULL, /* gm_spnego_canonicalize_name */
+    NULL, /* gm_spnego_duplicate_name */
     _gss_spnego_inquire_sec_context_by_oid,
     NULL, /* gm_inquire_cred_by_oid */
     _gss_spnego_set_sec_context_option,
index b59bbd83ae01ec2a1af079b6d38e3054dc936c36..b31a94771324de3abf9691387331ca32dd91fb31 100644 (file)
@@ -44,8 +44,10 @@ static char *type_string;
 static char *mech_string;
 static char *mechs_string;
 static char *ret_mech_string;
+static char *localname_string;
 static char *client_name;
 static char *client_password;
+static char *localname_string;
 static int dns_canon_flag = -1;
 static int mutual_auth_flag = 0;
 static int dce_style_flag = 0;
@@ -161,7 +163,7 @@ loop(gss_OID mechoid,
     int server_done = 0, client_done = 0;
     int num_loops = 0;
     OM_uint32 maj_stat, min_stat;
-    gss_name_t gss_target_name;
+    gss_name_t gss_target_name, src_name;
     gss_buffer_desc input_token, output_token;
     OM_uint32 flags = 0, ret_cflags, ret_sflags;
     gss_OID actual_mech_client;
@@ -236,7 +238,7 @@ loop(gss_OID mechoid,
                                          GSS_C_NO_CREDENTIAL,
                                          &output_token,
                                          GSS_C_NO_CHANNEL_BINDINGS,
-                                         NULL,
+                                         &src_name,
                                          &actual_mech_server,
                                          &input_token,
                                          &ret_sflags,
@@ -275,6 +277,49 @@ loop(gss_OID mechoid,
        errx(1, "mech mismatch");
     *actual_mech = actual_mech_server;
 
+    if (localname_string) {
+        gss_buffer_desc lname;
+
+        maj_stat = gss_localname(&min_stat, src_name, GSS_C_NO_OID, &lname);
+        if (maj_stat != GSS_S_COMPLETE)
+            errx(1, "localname: %s",
+                 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
+        if (verbose_flag)
+            printf("localname: %.*s\n", (int)lname.length,
+                   (char *)lname.value);
+        if (lname.length != strlen(localname_string) ||
+            strncmp(localname_string, lname.value, lname.length))
+            errx(1, "localname: expected \"%s\", got \"%.*s\" (1)",
+                 localname_string, (int)lname.length, (char *)lname.value);
+        gss_release_buffer(&min_stat, &lname);
+        maj_stat = gss_localname(&min_stat, src_name, actual_mech_server,
+                                 &lname);
+        if (maj_stat != GSS_S_COMPLETE)
+            errx(1, "localname: %s",
+                 gssapi_err(maj_stat, min_stat, actual_mech_server));
+        if (lname.length != strlen(localname_string) ||
+            strncmp(localname_string, lname.value, lname.length))
+            errx(1, "localname: expected \"%s\", got \"%.*s\" (2)",
+                 localname_string, (int)lname.length, (char *)lname.value);
+        gss_release_buffer(&min_stat, &lname);
+
+        if (!gss_userok(src_name, localname_string))
+            errx(1, "localname is not userok");
+        if (gss_userok(src_name, "nosuchuser:no"))
+            errx(1, "gss_userok() appears broken");
+    }
+    if (verbose_flag) {
+        gss_buffer_desc iname;
+
+        maj_stat = gss_display_name(&min_stat, src_name, &iname, NULL);
+        if (maj_stat != GSS_S_COMPLETE)
+            errx(1, "display_name: %s",
+                 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
+        printf("client name: %.*s\n", (int)iname.length, (char *)iname.value);
+        gss_release_buffer(&min_stat, &iname);
+    }
+    gss_release_name(&min_stat, &src_name);
+
     if (max_loops && num_loops > max_loops)
        errx(1, "num loops %d was lager then max loops %d",
             num_loops, max_loops);
@@ -593,6 +638,7 @@ static struct getargs args[] = {
      "server should get a credential", NULL },
     {"export-import-context",0,        arg_flag,       &ei_ctx_flag, "test export/import context", NULL },
     {"export-import-cred",0,   arg_flag,       &ei_cred_flag, "test export/import cred", NULL },
+    {"localname",0,     arg_string, &localname_string, "expected localname for client", "USERNAME"},
     {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL },
     {"session-enctype",        0, arg_string,  &session_enctype_string, "enctype", NULL },
     {"client-time-offset",     0, arg_integer, &client_time_offset, "time", NULL },
index 97e2e0c01c2a8b9eeea64aad24f3bb8ad157cf61..0b657fc178c53289adbadade9796bfe4715b7279 100644 (file)
@@ -217,6 +217,7 @@ for mech in krb5 krb5iov spnego spnegoiov; do
        echo "${mech} no-mutual ${iov}" ; > messages.log
        ${context} --mech-type=${mech} \
            --wrapunwrap ${iov} \
+            --localname=mapped_user1 \
            --name-type=hostbased-service host@lucid.test.h5l.se || \
                { eval "$testfailed"; }
 
index 2e469ecd3aac06e8862648258245eda0597e8900..69c16ad7e950dcb389df46ebf3b82e3a09d59afc 100644 (file)
@@ -4,10 +4,17 @@ include @srcdirabs@/include-krb5.conf
        default_keytab_name = @objdir@/server.keytab
         enable-kx509 = yes
         kx509_store = PEM-FILE:/tmp/cert_%{euid}.pem
+       default_realm = TEST.H5L.SE
+       kuserok = SYSTEM-K5LOGIN:@srcdir@/../kdc/k5login
+       kuserok = USER-K5LOGIN
+       kuserok = SIMPLE
 
 [realms]
        TEST.H5L.SE = {
                kdc = localhost:@port@
+                auth_to_local_names = {
+                        user1 = mapped_user1
+                }
        }
 
 [kdc]
index 39e1a50182eb89dbb63017737f79f3b096781921..0b2fe383e9c2ef57850ca510c7f4d4d46117970e 100644 (file)
@@ -73,6 +73,7 @@ mapped1@TEST2.H5L.SE m1
 mapped1@TEST3.H5L.SE mapped1
 mapped2@TEST2.H5L.SE m2
 mapped2@TEST3.H5L.SE mapped2
+user1@@TEST.H5L.SE mapped_user1
 z008213d189aac2b junk
 z07644c5c50f29d5 junk
 z094067ad439189c junk
diff --git a/tests/kdc/k5login/mapped_user1 b/tests/kdc/k5login/mapped_user1
new file mode 100644 (file)
index 0000000..a7857c2
--- /dev/null
@@ -0,0 +1 @@
+user1@TEST.H5L.SE