From: Simo Sorce Date: Wed, 30 Mar 2016 17:00:19 +0000 (-0400) Subject: Add SPNEGO special case for NTLMSSP+MechListMIC X-Git-Tag: krb5-1.15-beta1~187 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb96ca52a3354e5a0ea52e12495ff375de54f9b7;p=thirdparty%2Fkrb5.git Add SPNEGO special case for NTLMSSP+MechListMIC 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) --- diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c index bcebba8424..7862d98e3a 100644 --- a/src/lib/gssapi/spnego/spnego_mech.c +++ b/src/lib/gssapi/spnego/spnego_mech.c @@ -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. */