Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internet Explorer bodyless POST optimization with SPNEGO header and accept-incomplete not handled #346

Open
OlivierJaquemet opened this issue Apr 19, 2016 · 12 comments
Labels

Comments

@OlivierJaquemet
Copy link
Contributor

For file upload, Internet Explorer may send a bodyless POST request under circumstances described in the following posts :

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 an accept-incomplete negResult
  • does not yet contains the file (even though the Content-Length / Content-Type indicates otherwise) (I suppose sent in a third request)

internet explorer accept-incomplete

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)

@dblock
Copy link
Collaborator

dblock commented Apr 21, 2016

This looks like something we should implement, PRs with tests welcome!

@dblock dblock added the bug? label Apr 21, 2016
@OlivierJaquemet
Copy link
Contributor Author

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.

@dblock
Copy link
Collaborator

dblock commented Apr 22, 2016

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.

@OlivierJaquemet
Copy link
Contributor Author

Shame on me, I did not find this doc previouly.

@dblock
Copy link
Collaborator

dblock commented Apr 22, 2016

No worries @OlivierJaquemet :)

@fanste
Copy link

fanste commented May 2, 2016

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.

@OlivierJaquemet
Copy link
Contributor Author

@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).

@fanste
Copy link

fanste commented May 2, 2016

Thanks for your feedback. I will take a look at the referenced issue and patches.

@fanste
Copy link

fanste commented May 3, 2016

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>

@OlivierJaquemet
Copy link
Contributor Author

  <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>

@fanste
Copy link

fanste commented May 3, 2016

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.

@fanste
Copy link

fanste commented May 4, 2016

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:

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants