krb5 commit: Allow GSS mechs to force mechlistMIC in SPNEGO
Greg Hudson
ghudson at MIT.EDU
Thu May 8 15:20:04 EDT 2014
https://github.com/krb5/krb5/commit/bff6bbf52401f9464df365d76f0987fbf8101c5e
commit bff6bbf52401f9464df365d76f0987fbf8101c5e
Author: Simo Sorce <simo at redhat.com>
Date: Mon May 5 17:59:08 2014 -0400
Allow GSS mechs to force mechlistMIC in SPNEGO
During a SPNEGO negotiation, if the NTLMSSP mechanism is used and a
MIC is produced within the final initiator mechanism token, Microsoft
servers require a mechlistMIC even if NTLMSSP was the most preferred
mechanism.
In spnego_mech.c, add a helper function mech_requires_mechlistMIC
which queries the mechanism to determine whether we might need to
produce a mechlistMIC for interoperability. Call it after each call
to the mechanism's gss_init_sec_context and set sc->mic_reqd if it
returns true. Although only the second call to NTLMSSP will actually
ever return true, the first call makes the mechanism aware that the
SPNEGO implementation supports this feature.
[ghudson at mit.edu: clarified commit message and code]
ticket: 7907 (new)
src/lib/gssapi/spnego/spnego_mech.c | 37 +++++++++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index 7529c74..c9c1b11 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -474,6 +474,39 @@ create_spnego_ctx(void)
return (spnego_ctx);
}
+/* iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) samba(7165)
+ * gssntlmssp(655) controls(1) spnego_req_mechlistMIC(2) */
+static const gss_OID_desc spnego_req_mechlistMIC_oid =
+ { 11, "\x2B\x06\x01\x04\x01\xB7\x7D\x85\x0F\x01\x02" };
+
+/*
+ * Return nonzero if the mechanism has reason to believe that a mechlistMIC
+ * exchange will be required. Microsoft servers erroneously require SPNEGO
+ * mechlistMIC if they see an internal MIC within an NTLMSSP Authenticate
+ * message, even if NTLMSSP was the preferred mechanism.
+ */
+static int
+mech_requires_mechlistMIC(spnego_gss_ctx_id_t sc)
+{
+ OM_uint32 major, minor;
+ gss_ctx_id_t ctx = sc->ctx_handle;
+ gss_OID oid = (gss_OID)&spnego_req_mechlistMIC_oid;
+ gss_buffer_set_t bufs;
+ int result;
+
+ major = gss_inquire_sec_context_by_oid(&minor, ctx, oid, &bufs);
+ if (major != GSS_S_COMPLETE)
+ return 0;
+
+ /* Report true if the mech returns a single buffer containing a single
+ * byte with value 1. */
+ result = (bufs != NULL && bufs->count == 1 &&
+ bufs->elements[0].length == 1 &&
+ memcmp(bufs->elements[0].value, "\1", 1) == 0);
+ (void) gss_release_buffer_set(&minor, &bufs);
+ return result;
+}
+
/*
* Both initiator and acceptor call here to verify and/or create mechListMIC,
* and to consistency-check the MIC state. handle_mic is invoked only if the
@@ -1014,6 +1047,10 @@ spnego_gss_init_sec_context(
actual_mech, &mechtok_out,
ret_flags, time_rec,
&negState, &send_token);
+
+ /* Give the mechanism a chance to force a mechlistMIC. */
+ if (!HARD_ERROR(ret) && mech_requires_mechlistMIC(spnego_ctx))
+ spnego_ctx->mic_reqd = 1;
}
/* Step 3: process or generate the MIC, if the negotiated mech is
More information about the cvs-krb5
mailing list