]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Update SPNEGO hintName value to current spec 319/head
authorGreg Hudson <ghudson@mit.edu>
Fri, 21 Aug 2015 22:48:06 +0000 (18:48 -0400)
committerGreg Hudson <ghudson@mit.edu>
Tue, 25 Aug 2015 04:22:40 +0000 (00:22 -0400)
[MS-SPNG] currently specifies that the hintName field of NegHints
should contain "not_defined_in_RFC4178@please_ignore".  Heimdal
implements this behavior, but we instead try to include a display
name.  Implement the currently specified behavior, and add a test to
t_spnego.c to verify that the expected hint token is generated.

Further cleanup is possible; the negHints encoding is now constant (so
it does not need to be generated dynamically), and we could avoid
abusing the mechListMIC parameter of make_spnego_tokenInit_msg() to
transport it.

ticket: 8236 (new)

src/lib/gssapi/spnego/spnego_mech.c
src/tests/gssapi/t_spnego.c

index f3d5f092e4c945a4c04893471b9020691de0f2b8..ef76e1f1bd1992b1589c518181f0f7df3c1a737f 100644 (file)
@@ -191,7 +191,7 @@ static const gss_OID_set_desc spnego_oidsets[] = {
 };
 const gss_OID_set_desc * const gss_mech_set_spnego = spnego_oidsets+0;
 
-static int make_NegHints(OM_uint32 *, spnego_gss_cred_id_t, gss_buffer_t *);
+static int make_NegHints(OM_uint32 *, gss_buffer_t *);
 static int put_neg_hints(unsigned char **, gss_buffer_t, unsigned int);
 static OM_uint32
 acc_ctx_hints(OM_uint32 *, gss_ctx_id_t *, spnego_gss_cred_id_t,
@@ -1185,97 +1185,24 @@ put_neg_hints(unsigned char **buf_out, gss_buffer_t input_token,
 #define HOST_PREFIX    "host@"
 #define HOST_PREFIX_LEN        (sizeof(HOST_PREFIX) - 1)
 
+/* Encode the dummy hintname string (as specified in [MS-SPNG]) into a
+ * DER-encoded [0] tagged GeneralString, and place the result in *outbuf. */
 static int
-make_NegHints(OM_uint32 *minor_status,
-             spnego_gss_cred_id_t spcred, gss_buffer_t *outbuf)
+make_NegHints(OM_uint32 *minor_status, gss_buffer_t *outbuf)
 {
-       gss_buffer_desc hintNameBuf;
-       gss_name_t hintName = GSS_C_NO_NAME;
-       gss_name_t hintKerberosName;
-       gss_OID hintNameType;
        OM_uint32 major_status;
-       OM_uint32 minor;
        unsigned int tlen = 0;
        unsigned int hintNameSize = 0;
        unsigned char *ptr;
        unsigned char *t;
+       const char *hintname = "not_defined_in_RFC4178@please_ignore";
+       const size_t hintname_len = strlen(hintname);
 
        *outbuf = GSS_C_NO_BUFFER;
-
-       if (spcred != NULL) {
-               major_status = gss_inquire_cred(minor_status,
-                                               spcred->mcred,
-                                               &hintName,
-                                               NULL,
-                                               NULL,
-                                               NULL);
-               if (major_status != GSS_S_COMPLETE)
-                       return (major_status);
-       }
-
-       if (hintName == GSS_C_NO_NAME) {
-               krb5_error_code code;
-               krb5int_access kaccess;
-               char hostname[HOST_PREFIX_LEN + MAXHOSTNAMELEN + 1] = HOST_PREFIX;
-
-               code = krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION);
-               if (code != 0) {
-                       *minor_status = code;
-                       return (GSS_S_FAILURE);
-               }
-
-               /* this breaks mutual authentication but Samba relies on it */
-               code = (*kaccess.clean_hostname)(NULL, NULL,
-                                                &hostname[HOST_PREFIX_LEN],
-                                                MAXHOSTNAMELEN);
-               if (code != 0) {
-                       *minor_status = code;
-                       return (GSS_S_FAILURE);
-               }
-
-               hintNameBuf.value = hostname;
-               hintNameBuf.length = strlen(hostname);
-
-               major_status = gss_import_name(minor_status,
-                                              &hintNameBuf,
-                                              GSS_C_NT_HOSTBASED_SERVICE,
-                                              &hintName);
-               if (major_status != GSS_S_COMPLETE) {
-                       return (major_status);
-               }
-       }
-
-       hintNameBuf.value = NULL;
-       hintNameBuf.length = 0;
-
-       major_status = gss_canonicalize_name(minor_status,
-                                            hintName,
-                                            (gss_OID)&gss_mech_krb5_oid,
-                                            &hintKerberosName);
-       if (major_status != GSS_S_COMPLETE) {
-               gss_release_name(&minor, &hintName);
-               return (major_status);
-       }
-       gss_release_name(&minor, &hintName);
-
-       major_status = gss_display_name(minor_status,
-                                       hintKerberosName,
-                                       &hintNameBuf,
-                                       &hintNameType);
-       if (major_status != GSS_S_COMPLETE) {
-               gss_release_name(&minor, &hintName);
-               return (major_status);
-       }
-       gss_release_name(&minor, &hintKerberosName);
-
-       /*
-        * Now encode the name hint into a NegHints ASN.1 type
-        */
        major_status = GSS_S_FAILURE;
 
        /* Length of DER encoded GeneralString */
-       tlen = 1 + gssint_der_length_size(hintNameBuf.length) +
-               hintNameBuf.length;
+       tlen = 1 + gssint_der_length_size(hintname_len) + hintname_len;
        hintNameSize = tlen;
 
        /* Length of DER encoded hintName */
@@ -1295,12 +1222,11 @@ make_NegHints(OM_uint32 *minor_status,
                goto errout;
 
        *ptr++ = GENERAL_STRING;
-       if (gssint_put_der_length(hintNameBuf.length,
-                                 &ptr, tlen - (int)(ptr-t)))
+       if (gssint_put_der_length(hintname_len, &ptr, tlen - (int)(ptr-t)))
                goto errout;
 
-       memcpy(ptr, hintNameBuf.value, hintNameBuf.length);
-       ptr += hintNameBuf.length;
+       memcpy(ptr, hintname, hintname_len);
+       ptr += hintname_len;
 
        *outbuf = (gss_buffer_t)malloc(sizeof(gss_buffer_desc));
        if (*outbuf == NULL) {
@@ -1320,8 +1246,6 @@ errout:
                free(t);
        }
 
-       gss_release_buffer(&minor, &hintNameBuf);
-
        return (major_status);
 }
 
@@ -1357,7 +1281,7 @@ acc_ctx_hints(OM_uint32 *minor_status,
        if (ret != GSS_S_COMPLETE)
                goto cleanup;
 
-       ret = make_NegHints(minor_status, spcred, mechListMIC);
+       ret = make_NegHints(minor_status, mechListMIC);
        if (ret != GSS_S_COMPLETE)
                goto cleanup;
 
index 80df1bf6555de98a9e6d39803747557e1297e7ea..2483228b1b887a797bc0e7b1f23a3005fdaf5a51 100644 (file)
@@ -192,6 +192,42 @@ test_mskrb_oid(gss_name_t tname, gss_cred_id_t acred)
     free(stok.value);
 }
 
+/* Check that we return a compatibility NegTokenInit2 message containing
+ * NegHints for an empty initiator token. */
+static void
+test_neghints()
+{
+    OM_uint32 major, minor;
+    gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok;
+    gss_ctx_id_t actx = GSS_C_NO_CONTEXT;
+    const char *expected =
+        /* RFC 2743 token framing: [APPLICATION 0] IMPLICIT SEQUENCE followed
+         * by OBJECT IDENTIFIER and the SPNEGO OID */
+        "\x60\x47\x06\x06" "\x2B\x06\x01\x05\x05\x02"
+        /* [0] SEQUENCE for the NegotiationToken negtokenInit choice */
+        "\xA0\x3D\x30\x3B"
+        /* [0] MechTypeList containing the krb5 OID */
+        "\xA0\x0D\x30\x0B\x06\x09" "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"
+        /* [3] NegHints containing [0] GeneralString containing the dummy
+         * hintName string defined in [MS-SPNG] */
+        "\xA3\x2A\x30\x28\xA0\x26\x1B\x24"
+        "not_defined_in_RFC4178@please_ignore";
+
+    /* Produce a hint token. */
+    major = gss_accept_sec_context(&minor, &actx, GSS_C_NO_CREDENTIAL, &itok,
+                                   GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL,
+                                   &atok, NULL, NULL, NULL);
+    check_gsserr("gss_accept_sec_context(neghints)", major, minor);
+
+    /* Verify it against the expected contents, which are fixed as long as we
+     * only list the krb5 mech in the token. */
+    assert(atok.length == strlen(expected));
+    assert(memcmp(atok.value, expected, atok.length) == 0);
+
+    (void)gss_release_buffer(&minor, &atok);
+    (void)gss_delete_sec_context(&minor, &actx, NULL);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -264,6 +300,8 @@ main(int argc, char *argv[])
     test_mskrb_oid(target_name, verifier_cred_handle);
     test_mskrb_oid(target_name, GSS_C_NO_CREDENTIAL);
 
+    test_neghints();
+
     (void)gss_delete_sec_context(&minor, &initiator_context, NULL);
     (void)gss_delete_sec_context(&minor, &acceptor_context, NULL);
     (void)gss_release_name(&minor, &source_name);