]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add SPNEGO special case for NTLMSSP+MechListMIC
authorSimo Sorce <simo@redhat.com>
Wed, 30 Mar 2016 17:00:19 +0000 (13:00 -0400)
committerGreg Hudson <ghudson@mit.edu>
Sun, 29 May 2016 01:53:33 +0000 (21:53 -0400)
MS-SPNG section 3.3.5.1 documents an odd behavior the SPNEGO layer
needs to implement specifically for the NTLMSSP mechanism.  This is
required for compatibility with Windows services.

ticket: 8423 (new)

src/lib/gssapi/spnego/spnego_mech.c

index bcebba84242b621381bcb3b436a7ece44f2cb4c1..7862d98e3a4966218c6afc0ac191ac2ea15a7710 100644 (file)
@@ -507,6 +507,45 @@ mech_requires_mechlistMIC(spnego_gss_ctx_id_t sc)
        return result;
 }
 
+/* iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) Microsoft(311)
+ * security(2) mechanisms(2) NTLM(10) */
+static const gss_OID_desc gss_mech_ntlmssp_oid =
+       { 10, "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a" };
+
+/* 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" };
+
+/*
+ * MS-SPNG section 3.3.5.1 warns that the NTLM mechanism requires special
+ * handling of the crypto state to interop with Windows.  If the mechanism for
+ * sc is SPNEGO, invoke a mechanism-specific operation on the context to reset
+ * the RC4 state after producing or verifying a MIC.  Ignore a result of
+ * GSS_S_UNAVAILABLE for compatibility with older versions of the mechanism
+ * that do not support this functionality.
+ */
+static OM_uint32
+ntlmssp_reset_crypto_state(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
+                          OM_uint32 verify)
+{
+       OM_uint32 major, minor;
+       gss_buffer_desc value;
+
+       if (!g_OID_equal(sc->internal_mech, &gss_mech_ntlmssp_oid))
+               return GSS_S_COMPLETE;
+
+       value.length = sizeof(verify);
+       value.value = &verify;
+       major = gss_set_sec_context_option(&minor, &sc->ctx_handle,
+                                          (gss_OID)&ntlmssp_reset_crypto_oid,
+                                          &value);
+       if (major == GSS_S_UNAVAILABLE)
+               return GSS_S_COMPLETE;
+       *minor_status = minor;
+       return major;
+}
+
 /*
  * 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
@@ -588,6 +627,8 @@ process_mic(OM_uint32 *minor_status, gss_buffer_t mic_in,
                ret = gss_verify_mic(minor_status, sc->ctx_handle,
                                     &sc->DER_mechTypes,
                                     mic_in, &qop_state);
+               if (ret == GSS_S_COMPLETE)
+                       ret = ntlmssp_reset_crypto_state(minor_status, sc, 1);
                if (ret != GSS_S_COMPLETE) {
                        *negState = REJECT;
                        *tokflag = ERROR_TOKEN_SEND;
@@ -602,6 +643,8 @@ process_mic(OM_uint32 *minor_status, gss_buffer_t mic_in,
                                  GSS_C_QOP_DEFAULT,
                                  &sc->DER_mechTypes,
                                  &tmpmic);
+               if (ret == GSS_S_COMPLETE)
+                       ret = ntlmssp_reset_crypto_state(minor_status, sc, 0);
                if (ret != GSS_S_COMPLETE) {
                        gss_release_buffer(&tmpmin, &tmpmic);
                        *tokflag = NO_TOKEN_SEND;
@@ -804,11 +847,6 @@ init_ctx_nego(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc,
        return ret;
 }
 
-/* iso(1) org(3) dod(6) internet(1) private(4) enterprise(1) Microsoft(311)
- * security(2) mechanisms(2) NTLM(10) */
-static const gss_OID_desc gss_mech_ntlmssp_oid =
-       { 10, "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a" };
-
 /*
  * Handle acceptor's counter-proposal of an alternative mechanism.
  */