diff options
-rw-r--r-- | src/lib/gssapi/spnego/spnego_mech.c | 50 |
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); |