-
Notifications
You must be signed in to change notification settings - Fork 187
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
Java SPNego bug #167
Comments
You should be able to turn this into a spec, which will make it easy to fix. Thanks for reporting it. |
Reviewing changes logs.
Support for SPNego was added by @AriSuutariST. Possibly this user can assist on this. |
Will try to write test for this issue, but I need some time to do it since I am no too experienced with Java projects. |
Hi, We are using waffle.apache.NegotiateAuthenticator valve at several sites and the SPNego stuff seems to work ok with it. However, I must admit that code I added only detects that those packets are related to authentication and should not be passed to application (for example a servlet). I'm not familiar how Waffle processes the packet after it has been classfied as authentication data, but it makes sense that NegTokenArg might require different processing as it is related to previous NegTokenInit. |
@ WiktorS is it possible to verify if this still exists and based on your last comment I'm hoping last year has seen great growth for you with java. If so, we would love to see a PR for this issue if it still exists. |
Totally forgot about this issue... I will verify this within few days |
We are observing the same issue and I have a reproduction procedure using ajax request and Internet Explorer : The symptoms :
This leads to an invalid 401 Unauthorized being sent. To reproduce : You can easily reproduce this problem with the following HTML test page:
Put this page on any site for which authentication is handled by waffle. |
With waffle 1.5 messages with SPNEGO auth ended up into application servlet calls, that's why I first spotted that some functionality was missing. I think that stuff added in 1.6 should be quite ok, but NegTokenArg stuff added in 1.7 might be the problem as the method to detect the authentication packet is not really solid (there is no signature that could be used for detection). Could you try with 1.6, just to see if it works in this situation ? We have 1.7 in use in production sites, but there might be no zero-length ajax requests in our application. |
@AriSuutariST I'll do a test with 1.6 during the hours to come. In the mean time, you can also test an ajax request on your site with the simple html file I gave above which I guarantee will not modify anything:)
|
Just tested on production site, your javascript example works there (HTTP 200 response) with Waffle 1.7.4, Win 2012 R2, Tomcat 7, JDK 1.8. |
Damn. Did you test with IE ? |
Yes, Win 10 + IE11. I'm using Valve in tomcat like this:
But please check with 1.6 if you can. |
I'll do a test as soon as I can today. but I have other pending tasks to do before. |
@dblock To avoid resetSecurityToken() mentioned in first comment, I think waffle needs extra method to AuthorizationHeader, maybe something like isNtlmType1PostAuthorizationHeaderContinuation() as original design does not (to my understanding) handle cases where multi-packet negotiation is used for authorization. That new method could return true when we have NegTokenArg header, false for all other cases. |
I just tested my test.html file on previous version :
One important difference regarding your setup @AriSuutariST , I'm not using I am really willing to help you on this matter, for example by modifying the source code (specially |
I was hoping that 1.6 would work. Now I'm out of ideas how to fix this :-( |
@hazendaz said in in first comment that support was added in 1.6 as PR #40... wouldn't it be logical that this is the source of problem ? |
I just configured by development system with filter instead of valve. Works ok... I wonder what is For authentication there is no difference if the request is ajax or not. The problems is somewhere else. |
Maybe the zero Content-Length confuses some layer in Waffle to think that request is authentication when it is not. |
I was able to reproduce the original issue now. I'll try to fix it first. |
@AriSuutariST since you can reproduce I think you're in the best place to fix it, looking forward to a pull request. |
When a PR comes along...please submit to master and 1.7 branch. I'll cut a fix for both so java 6 users are not left out. Sent from Outlook Mobile On Thu, Mar 24, 2016 at 5:38 AM -0700, "Daniel Doubrovkine (dB.) @dblockdotorg" [email protected] wrote: @AriSuutariST since you can reproduce I think you're in the best place to fix it, looking forward to a pull request. You are receiving this because you were mentioned. |
I'm currently debugging it and trying to obtain better understanding what is really going on. Anyway, this is going to take some days so don't hold your breath yet :-) |
I see why this occurs with zero-length POST now. AuthorizationHeader.isNtlmType1PostAuthorizationHeader() returns false if contentLength() != 0. |
This is what I was trying to tell when i was reffering to I just did a debugging session with my reproduction step, and it seems to me the problem starts in
The implementation of
|
It is important to detect which post as only for authentication - otherwise your application starts receiving spurious zero-length post-requests. I think that it was to reason why I started digging into SPNEGO headers in first place. I think that original idea in isNtlmType1PostAuthorizationHeader() is this filtering, but I'm not sure. I just mimicked same design for SPNEGO headers. But now the method is used for controlling in resetSecurityToken() calls also, which might be wrong. If the token is bound to connection is there ever a situation where it should be reset (as it is 'reset' for new connections, I suppose). So would the correct fix be to:
The last one is actually not that simple. It seems that browser sends post data |
@OlivierJaquemet I'll be away for a few days, but I'll continue digging into this (unless it has been solved before I get back). |
Thank for your explanation of all aspects of this subject @AriSuutariST. |
I have been thinking how to get this working in more robust way. Currently isNtlmType1PostAuthorizationHeader() logic is used for two things (based on browsing the source code):
The later was the original reason for me to start working with SPNEGO stuff. I didn't realize the first case at the time. I think too that @OlivierJaquemet is correct here, resetSecurityToken call is completely unnecessary. This is because authentication is per each connection. For new connection, no resetting is needed as it is already in "reset" state. For old connection, server / browser will not renegotiate it. So that part of current code could just be removed without any harm. This leaves filtering out POST/PUTs which are only for authentication (see rfc4559 chapter 6 for details). Maybe instead of trying to decode data in Authorization header isNtlmType1PostAuthorizationHeader() could be implemented by just checking if Authorization header starts with "Negotiate" word and content-length is zero. Please comment, I'll make the changes if this makes sense to others. |
My solution to stop zero-length post leaking to application in PR #76 is wrong as isNtlmType1PostAuthorizationHeader() is expected to return true only packets that start new authentication. NegTokenArg never occurs as first packet. NegTokenInit processing should be OK, as it behaves same way as NTLM type 1 packet. The problem that #76 was trying to address must be handled in different way (don't know how yet). Also, the case where application deliberately sends zero-length post must be tested (as it seems to be difficult to separate if browser is starting new authentication or application is sending zero-lenght post). |
@AriSuutariST Are you saying we should revert #76? |
Partly, yes. Not completely, because it will cause problems when authentication headers using NegTokenArg data are used with POST - they leak to application, confusing it. NegTokenArg stuff is difficult to test, I wish I knew how to trigger such negotiation that they are used. I have it occurring on large production system, but not on my test environment. On my test environment, authentication completes after first GET/POST having "Authorize: Negotiate ...." header set. However, I don't object reverting #76, it would fix the original issue in this thread. |
These issues seem to be two separate ones. Original one about negotiation loosing context when NegTokenArg and the one reported by @OlivierJaquemet with zero-length ajax post (where packet trace shows only NegTokenInit). When IE uses SPNEGO and has already autheticated with previous requests, it seems to blindly send Negotiate header with post. It is correct that in such case Waffle calls resetSecurityToken. Waffle even handles to Negatiate data OK after that, but fails on NegotiateSecurityFilterProvider:159 where it checks if it should sent SC_UNAUTHORIZED or not. I think that idea behind this in IE (sending the authentication info with post data) is performance optimization, it avoids unncessary round-trip with content-length=0 when it knows that SPNEGO auto should be valid based on previous GETs/POSTs. |
OliverJaquemet pointed me to this issue, as I have a similar error in IE11. I've applied both fixes (338, 339) but the error sill occurs. Let me explain it and please tell me, if it might be related or not. I'm using waffle-jna (servlet, JSF) to do single-sign-on on our company applications. Everything seems to work until a XHR file upload is performed. IE11 seems to send a special request that should test, if authentication is required (no post data but content length != 0). This is done to not waste bandwidth as the uploaded data is thrown away if auth is required. I don't have the log with me (I will confirm this tomorrow) but as far as I remember it ends in I will try to gather more information tomorrow. |
Really no POST data but Content-Length > 0 ? Because all other special authentication stuff related to post works so that POST has Content-Length: 0 but carries authentication headers. If Content-Length indicates that there should be data and there isn't I think that is not IE optimization, but something goes so wrong that IE negotiation just drops dead and it closes the connection. These are sometimes hard to reproduce by others, maybe sharing wireshark traffic dumps of problematic cases would be helpful. |
You are right. I've missed one request which is the zero-length POST request. It returns with 401, IE responds but fiddler tells me, that no data is sent. Additionally the second request sometimes doesn't appear in my log... I will get you a traffic dump. |
@fanste Are you using Tomcat, with valve or filter ? |
I'm using waffle as a filter on JBoss 7.1.3 (waffle is added as a module inside JBoss). Some more findings (until dump is made):
|
This looks different than the problems in this issue, not related to SPNEGO/Kerberos, as this is all NTLM authentication. It would be nice to see rest of the packets in failed overview, now there is only the initial zero-length post and server response. |
@fanste Given your capture, and contrary to what I initially thought and stated, you migh be observing the same issue I reported in #346 |
@AriSuutariST I can't give you more packets as the communication stops at that point. Within another capture there is one more package that delivers the 500 status code back to the client which indicates the read timeout (2 minutes) of the upload. @OlivierJaquemet Alright :D Then I have to find out how Kerberos is configured in waffle and how I'm able to use this within our company. |
I think there is a bug introduced in waffle 1.7.
AuthorizationHeader.isNtlmType1PostAuthorizationHeader() returns true for both SPNego message types (NegTokenInit or NegTokenArg), what causes call of auth.resetSecurityToken() inside NegotiateSecurityFilterProvider.doFilter().
Negotiation looses context when NegotiateSecurityFilterProvider receives NegTokenArg message.
This might be problem inside my code since I am implementing my own HttpServletRequest and HttpServletResponse interfaces, but it works in waffle 1.5 and 1.6.
WS
The text was updated successfully, but these errors were encountered: