summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2014-05-05 17:59:08 -0400
committerGreg Hudson <ghudson@mit.edu>2014-05-08 15:19:10 -0400
commitbff6bbf52401f9464df365d76f0987fbf8101c5e (patch)
tree3ab068c0f96ccd6e86742a1f1192b43274ae5d05
parent60234f7b4cef58b66e0b2776988dfcf79c0d8bbb (diff)
downloadkrb5-bff6bbf52401f9464df365d76f0987fbf8101c5e.tar.gz
krb5-bff6bbf52401f9464df365d76f0987fbf8101c5e.tar.xz
krb5-bff6bbf52401f9464df365d76f0987fbf8101c5e.zip
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@mit.edu: clarified commit message and code] ticket: 7907 (new)
-rw-r--r--src/lib/gssapi/spnego/spnego_mech.c37
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 7529c7426..c9c1b1165 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