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