summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/gssapi/spnego/spnego_mech.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index bcebba842..ae1bb3b74 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -960,6 +960,34 @@ fail:
return ret;
}
+/* iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) samba(7165)
+ * gssntlmssp(655) controls(1) ntlmssp_reset_crypto(3) */
+static const gss_OID_desc ntlmssp_reset_crypto_oid =
+ { 11, "\x2B\x06\x01\x04\x01\xB7\x7D\x85\x0F\x01\x03" };
+
+static int
+ntlmssp_reset_crypto_state(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc)
+{
+ OM_uint32 major, minor;
+ gss_OID oid = (gss_OID)&ntlmssp_reset_crypto_oid;
+ OM_uint32 reset_seq = 0;
+ gss_buffer_desc value = { sizeof(OM_uint32), &reset_seq };
+
+ if (!sc->mic_rcvd) {
+ reset_seq = 1;
+ }
+
+ major = gss_set_sec_context_option(&minor, &sc->ctx_handle, oid,
+ &value);
+ /* ignore if not available */
+ if (major == GSS_S_UNAVAILABLE) {
+ major = GSS_S_COMPLETE;
+ } else {
+ *minor_status = minor;
+ }
+ return major;
+}
+
/*ARGSUSED*/
OM_uint32 KRB5_CALLCONV
spnego_gss_init_sec_context(
@@ -1072,6 +1100,18 @@ spnego_gss_init_sec_context(
spnego_ctx, &mechListMIC_out,
&negState, &send_token);
}
+ if (ret == GSS_S_COMPLETE) {
+ /*
+ * MS-SPNG 3.3.5.1 warns hat the NTLM mechanism requires
+ * special handling of the crypto state to interop with
+ * Windows.
+ */
+ if (g_OID_equal(spnego_ctx->internal_mech,
+ &gss_mech_ntlmssp_oid)) {
+ ret = ntlmssp_reset_crypto_state(minor_status,
+ spnego_ctx);
+ }
+ }
cleanup:
if (send_token == INIT_TOKEN_SEND) {
if (make_spnego_tokenInit_msg(spnego_ctx,
@@ -1702,6 +1742,16 @@ spnego_gss_accept_sec_context(
sc, &mic_out,
&negState, &return_token);
}
+ if (ret == GSS_S_COMPLETE) {
+ /*
+ * MS-SPNG 3.3.5.1 warns hat the NTLM mechanism requires
+ * special handling of the crypto state to interop with
+ * Windows.
+ */
+ if (g_OID_equal(sc->internal_mech, &gss_mech_ntlmssp_oid)) {
+ ret = ntlmssp_reset_crypto_state(minor_status, sc);
+ }
+ }
cleanup:
if (return_token == INIT_TOKEN_SEND && sendTokenInit) {
assert(sc != NULL);