krb5 commit: Update SPNEGO hintName value to current spec

Greg Hudson ghudson at mit.edu
Tue Aug 25 00:29:46 EDT 2015


https://github.com/krb5/krb5/commit/c8e9758db1d8a536a1404187b5911a96f7cdbea3
commit c8e9758db1d8a536a1404187b5911a96f7cdbea3
Author: Greg Hudson <ghudson at mit.edu>
Date:   Fri Aug 21 18:48:06 2015 -0400

    Update SPNEGO hintName value to current spec
    
    [MS-SPNG] currently specifies that the hintName field of NegHints
    should contain "not_defined_in_RFC4178 at 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 |   98 ++++-------------------------------
 src/tests/gssapi/t_spnego.c         |   38 +++++++++++++
 2 files changed, 49 insertions(+), 87 deletions(-)

diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index f3d5f09..ef76e1f 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -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 at 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;
 
diff --git a/src/tests/gssapi/t_spnego.c b/src/tests/gssapi/t_spnego.c
index 80df1bf..2483228 100644
--- a/src/tests/gssapi/t_spnego.c
+++ b/src/tests/gssapi/t_spnego.c
@@ -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 at 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);


More information about the cvs-krb5 mailing list