waffle
waffle copied to clipboard
Internet Explorer bodyless POST optimization with SPNEGO header and accept-incomplete not handled
For file upload, Internet Explorer may send a bodyless POST request under circumstances described in the following posts :
- https://blogs.msdn.microsoft.com/ieinternals/2010/11/21/challenge-response-authentication-and-zero-length-posts/
- http://stackoverflow.com/questions/20912663/ie10-ie11-upload-fail-not-sending-post-data
In such case, the behavior of the server as expected by IE is to send a 401 request to "re-establish" the authentication. However, in my observations, when this IE "optimization" occurs, the subsequent request
- contains and HTTP header
Authorization: Negotiate
, with an SPNegoTokenTarg message with anaccept-incomplete
negResult - does not yet contains the file (even though the Content-Length / Content-Type indicates otherwise) (I suppose sent in a third request)
Looking at the RFC : https://www.ietf.org/rfc/rfc4178.txt
The accept-incomplete
indicates the following : "At least one additional negotiation message from the peer is needed to establish the security context."
Indeed, the MSDN, documentation for AcceptSecurityContext
indicates the possible SEC_I_COMPLETE_AND_CONTINUE
or SEC_I_COMPLETE_NEEDED
return value which requires additionnal processing :
https://msdn.microsoft.com/en-us/library/windows/desktop/aa374705(v=vs.85).aspx
waffle-jna implementation in WindowsAuthProviderImpl.acceptSecurityToken
does not seem to be handling such case :
https://github.com/dblock/waffle/blob/60451c353916863d93073a32e88006af28c94412/Source/JNA/waffle-jna/src/main/java/waffle/windows/auth/impl/WindowsAuthProviderImpl.java#L134:L170
(The result for the end user is an upload failure)
This looks like something we should implement, PRs with tests welcome!
As far as I am concerned, there a lot of work before getting even near to a PR, I need to get familiar with the code base, the test suite, and most of all the build and process... This will not happen anytime soon. If you could pinpoint some documentation, thread, or anything describing the build process and potentialy some architecture choice of Waffle, It might speed up my learning.
There's quite a bit in https://github.com/dblock/waffle/blob/master/Docs/SettingUpDevelopmentEnvironment.md, and maybe as you work through it you can contribute for the next person to get started.
Shame on me, I did not find this doc previouly.
No worries @OlivierJaquemet :)
Any progress on this issue?
We've recently upgraded to IE11 in our company and XHR-based file uploads started to fail from time to time. As soon as I remove waffle from the filter-chain (JSF based application) it works all the time.
@fanste the issue you are facing is probably not this one which happens only when using NTLMSSP (not kerberos), under very rare circumstances.
Issue #167 is certainly the source of the problem you are observing. I had a similar bug and I could test the solution implemented by @AriSuutariST in #338 and #339 with success . As far as I know #339 has not yet been merged due to unittest issues so it is probably not yet planned for 1.8.2. In the meantime you can checkout the corresponding branch to apply and test the fix (and it would be nice to do so as it would add a second confirmation of proper implementation).
Thanks for your feedback. I will take a look at the referenced issue and patches.
After you got me back to this issue, I have a question: What is your waffle filter configuration? I've tried to produce a capture that is similar to yours. But it always tries to use Kerberos if I enable Negotiation. This results in KRB5KRB_AP_ERR_MODIFIED
as Kerberos is not configured.
<filter>
<filter-name>NtlmHttpFilter</filter-name>
<filter-class>waffle.servlet.NegotiateSecurityFilter</filter-class>
<init-param>
<param-name>waffle.servlet.spi.NegotiateSecurityFilterProvider/protocols</param-name>
<param-value>Negotiate</param-value>
</init-param>
</filter>
<init-param>
<param-name>securityFilterProviders</param-name>
<param-value>
waffle.servlet.spi.NegotiateSecurityFilterProvider
</param-value>
</init-param>
<init-param>
<param-name>waffle.servlet.spi.NegotiateSecurityFilterProvider/protocols</param-name>
<param-value>
Negotiate
NTLM
</param-value>
</init-param>
NTLM is only used for the local server instance (negTokenInit > mechTypes has it as its first element). Our testserver (somewhere in the comanies network) has MS KRB5 as its first element. I'm now using RawCap to capture the traffic of the local server.
If I've understood your first post correctly, than we have the same issue. But I have a small difference: Wireshark does not show the parsed packet for POST NTLMSSP_AUTH
. It gets confused by the Content-Length > 0
and missing POST body.
I've modified NegotiateSecurityFilterProvide#isPrincipalException
so that the method consideres an previously cached ContinueContext
for the current connectionId
. It is then able to invoke the auth provider impl (resp. Secur32.INSTANCE.AcceptSecurityContext
) one more time and the returned token contains negResult=accept-completed
. I've never hit SEC_I_COMPLETE_AND_CONTINUE
or SEC_I_COMPLETE_NEEDED
. Then I modified the filter in a way, that the first ntlmPost
will set a flag for the connectionId
to true
which is again used as soon as the negotiation succeeded (SEC_E_OK
) to return back to the client without forwarding the request to the application (remember: Content-Length > 0
but no POST data). It doesn't matter if I return with status 200 or 401, IE will never send the next request. The IE network tab shows the request as pending
... forever.
Either we've hit a serious bug within IE itself or the usage of the WinAPI is incorrect (missing flags or missing additional API calls). But I'm out of ideas and far away from being a pro in concerns of NTLM.
I think we can stop digging around as the error is not only within waffle but also occurs with Microsoft IIS 7.5. Must be a bug inside IE...
I've found the following links from microsoft, but the don't fix it for me:
- https://support.microsoft.com/en-us/kb/2980019
- https://technet.microsoft.com/library/security/ms14-052
- https://www.microsoft.com/en-us/download/details.aspx?id=44202
Edit 04.05.2016 11:03: I've had the possibility to test that feature on a windows 10 machine using IE11 and the new edge browser. It's working on both browsers. I can't tell you if it has something to do with the browser itself or if it is a windows internal thing (bug in the NTLM implementation or something like that). The same round-trips are done if IE expects a 401. It first sends a zero-length POST request followed by an request containing the POST data. This was tested using waffle 1.6.1224.