protocols configuration - Negotiate vs NTLM

Aug 4, 2010 at 1:10 PM
Edited Aug 4, 2010 at 1:13 PM

I'm using the waffle.servlet.NegotiateSecurityFilter with the following configuration.

    <filter>
        <filter-name>SecurityFilter</filter-name>
        <filter-class>waffle.servlet.NegotiateSecurityFilter</filter-class>
        <init-param>
            <param-name>allowGuestLogin</param-name>
            <param-value>false</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>SecurityFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

In my test scenarios everything worked as expected.

Now I'm using it in a different environment and I'm having some problems. Two different browsers access my application. Client A is authenticated successfully but Client B is not authenticated (Internet Explorer cannot display the webpage"). Because of some restrictions it's not possible to disable the "friendly" http error messages in IE but I suspect that it is HTTP 401.

Client A and Client B are both using Windows XP SP2 with IE6 in the same domain and same logon server.

The logfile shows for Client B (the one which is not working) just the line "authorization required" and nothing more.

The Browser shows for Client A "Local Intranet" and for Client B "Internet". If I deactivate the NegotiateSecurityFilter and the clients logon manually, both Browsers show "Local Intranet".

The next step was, that I reactivated the old jcifs.http.NtlmHttpFilter and the SSO worked sucessfully for both Clients.

Then I changed the waffle filter configuration to the following (first NTLM, second Negotiate):

    <filter>
        <filter-name>SecurityFilter</filter-name>
        <filter-class>waffle.servlet.NegotiateSecurityFilter</filter-class>
        <init-param>
            <param-name>allowGuestLogin</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
         <param-name>waffle.servlet.spi.NegotiateSecurityFilterProvider/protocols</param-name>
         <param-value>
            NTLM
             Negotiate
         </param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>SecurityFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

This configuration works fine for Client A and B. Both clients are sucessfully authenticated using waffle.

Any idea what's going on here? Is this configuration the better default configuration?

Coordinator
Aug 4, 2010 at 1:22 PM
Edited Aug 4, 2010 at 1:24 PM

It looks like your client B won't do Kerberos, but is happy to do NTLM. This is confirmed with your NtlmHttpFilter that only does that. Client B gets Authorization: Negotiate (and others), then tries to do something with Kerberos, fails and doesn't fall back to NTLM.

First you should verify the above by looking at the HTTP trace (try IEHttpHeaders). Your client B will make a single request, then do nothing about it.

I would then check that client B has the exact same security settings. Specifically Tools->Internet Options->Advanced->Security, start with "Enable Integrated Windows Authentication". Then all the other settings.

Your client B thinks that the server is not in the intranet. What's the URL? Maybe it has saved it as being in the internet zone, try re-adding this server to the Intranet zone and maybe resetting the security zones altogether.

Then, try wfetch, see http://support.microsoft.com/default.aspx?scid=kb;en-us;284285. It should hopefuly tell you what the client side problem with Kerberos is.

Aug 4, 2010 at 2:17 PM

Thanks for the quick reply. Sadly the clients in question are really shielded, meaning, it's not possible to change IE settings, or install add-ons, etc. The security settings should be identically. IWA is active.

Client B thinks that the server is not in the intranet only if negotiate is active. With NTLM it is in the "local intranet". The url is something like http://servername:8080/ It's not a fully qualified name.

wfetch looks interesting. I will take a look and test it internally. I'm not sure that I can use it on the client side. So, for the time being I will stick with the changed protocols parameters (NTLM, Negotiate) for this installation.

Coordinator
Aug 4, 2010 at 3:13 PM

Clearly, when A and B should be identical, A works and B doesn't, they are not identical :) I think you're fine using NTLM as the first protocol choice especially because you still have IE6 out there. I have a ton of customers on IE6 and it makes my hair grey, I think they are insane - Internet Explorer 6 patch support has ended, the next critical vulnerability will not be patched and it will be a major emergency whereever you are.

Aug 4, 2010 at 9:26 PM

Yes, obviously they can not be identical, but it's really difficult to find the differences, because there are so many different parts and you are not allowed to inspect the system with better tools than the ones windows has installed by default ;-)

I don't understand it either, why IE 6 is still used. Life could be much easier without...

Another question. If I configure the protocols with NTLM as the first protocol in the filter configuration, does this include NTLMv1 and NTLMv2?

If NTLM is the first protocol but NTLM is forbidden in the domain environment, is automatically Negotiate with Kerberos used if it is configured as the second protocol? I wasn't able to test the different scenarios yet...

Coordinator
Aug 5, 2010 at 12:48 PM
Edited Aug 5, 2010 at 12:48 PM

There's an article about how client and server negotiate NTLM version and what registry keys are used to enable/disable v1, v2, etc. From what I understand newer clients will always try to do Kerberos -> NTLMv2 -> LM in this order, but older ones (like your IE6 on a wheelbarrow Windows 95) may try to do v1 unless it's disabled.

I think you can't disable NTLM altogether. And NTLMv2 is basically Kerberos under the hood, so it's equally strong. Disabling LM (NTLMv1) at the domain level is the "right way" of enforcing NTLMv2 everywhere.

Mar 2, 2011 at 1:01 PM
Edited Mar 2, 2011 at 4:10 PM

Currently I'm experimenting with Kerberos authentication (value "Negotiate" for the parameter "waffle.servlet.spi.NegotiateSecurityFilterProvider/protocols"). I found this article http://support.microsoft.com/kb/327825/en-us "Problems with Kerberos authentication when users belong to many groups" and I assume it may be the reason for my old problem (Client A works with Kerberos, Client B doesn't). In Tomcat the default maximum size of the request and response HTTP header is 4096 (4 KB). If the Kerberos ticket is larger, it doesn't fit in the header and the authentication fails. So, to workaround this it's necessary the modify the server.xml in Tomcat and add a "maxHttpHeaderSize" attribute to the Connector (e.g. value 32768 for 32 KB or 16384 for 16 KB).

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               maxHttpHeaderSize="32768" />

I could not try if this would really solves the problems which I had, but it's something to look out for if Kerberos works for some users and fails for others.

UPDATE:

I just had a case where the Kerberos ticket was 4349 bytes and the authentication failed. The logfile of the Apache Tomcat server ends with the following line:

waffle.servlet.NegotiateSecurityFilter - authorization required

The ieHttpHeaders console on the client in IE shows:

HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Date: Wed, 02 Mar 2011 16:01:12 GMT
Connection: close

The solution is to increase the maxHttpHeaderSize for the Connector, as I wrote before.

I haven't looked at the NegotiateSecurityFilter source code, but maybe it's possible to show a better error message for this case.

Coordinator
Mar 3, 2011 at 1:32 PM

Nice one. I've added this to the FAQ. If you have a patch that makes the error message better, go for it.