2

I am using following filter to enable NTLM Authentication, in my web-application.

I get the windows browser authentication prompt. It is working fine. Except for the fact that - I am unable to tell if Authentication Succeeded or Failed !!! *There are no errors in either case.* In every case username(correct or otherwise), workstation etc. is printed.

package com.test;
import java.io.IOException;
import java.io.PrintStream;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jcifs.ntlmssp.Type3Message;
import com.sun.xml.internal.ws.util.StringUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class NTLMUserFilter implements Filter {
    private FilterConfig filterConfig = null;
    private String userDomain = null;
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }
    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        String username = null;
        //first, get the user agent
        String useragent = request.getHeader("user-agent");
        //if you're using IE, you can continue
        if ((useragent.indexOf("MSIE") > -1)){
            //Always do the ntlm check (for IE POST back)
            try{
                String auth = request.getHeader("Authorization");
                if (auth == null)
                {
                  response.setHeader("WWW-Authenticate", "NTLM");
                  response.setStatus(response.SC_UNAUTHORIZED);
                  response.setContentLength(0) ;
                  response.flushBuffer();
                  return;
                }
                if (auth.startsWith("NTLM "))
                {
                  byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
                  int off = 0, length, offset;
                  if (msg[8] == 1)
                  {
                    byte z = 0;
                    byte[] msg1 = {(byte)'N', (byte)'T', (byte)'L', (byte)'M', (byte)'S', (byte)'S', (byte)'P', z,(byte)2, z, z, z, z, z, z, z,(byte)40, z, z, z, (byte)1, (byte)130, z, z,z, (byte)2, (byte)2, (byte)2, z, z, z, z, z, z, z, z, z, z, z, z};
                    response.setHeader("WWW-Authenticate", "NTLM " + new sun.misc.BASE64Encoder().encodeBuffer(msg1));
                    response.setStatus(response.SC_UNAUTHORIZED);
                    response.setContentLength(0) ;
                    response.flushBuffer();
                    return;
                  }
                  else if (msg[8] == 3)
                  {
                      //Did Authentication Succeed? All this is always printed.

                      Type3Message type3 = new Type3Message(msg);

                      System.out.println("osUser: " + type3.getUser());
                      System.out.println("osRemoteHost: + " + type3.getWorkstation());
                      System.out.println("osDomain: " + type3.getDomain());

                  }
                }
            }catch(Exception e){
                System.out.println(e) ;
            }
            //System.out.println("Suc);


            }

        try {
            chain.doFilter(req, res);
        } catch (IOException e) {
            System.out.println(e);
        } catch (ServletException e) {
            System.out.println(e);
        }
    }
public void destroy()
   {
     this.filterConfig = null;
   }
}

The web.xml is simple:

<filter>
    <filter-name>ntlmFilter</filter-name>
    <filter-class>
        com.test.NTLMUserFilter
    </filter-class>
</filter>

<!-- Filter mapping configuration   -->

<filter-mapping>
    <filter-name>ntlmFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>   

Jasper
  • 8,440
  • 31
  • 92
  • 133
  • Have you tried capturing the messages from both a succeeded and a failed logon, and comparing them side by side? – Wug Aug 06 '12 at 15:15

2 Answers2

3

As Edward said, just extracting a name from a type 3 (response) NTLM message doesn't say anything about whether the client who generated it was entitled to do so.

NTLM is not like Kerberos, where there's a signed token that a service can validate on its own; you have to make a connection to the domain controller every time to ask it whether the token is legit. Implementing an MSRPC connection to check an NTLM token is really hard work.

In the old days you could do this in JCIFS using a jcifs.smb.SmbSession, and jcifs.http.NtlmHttpFilter would do just that for you. However, this only works for NTLMv1, which is old, insecure, and increasingly unlikely to be used for anything. (I believe 'ntlm-java' linked above is also NTLMv1-only.)

Try the ntlmv2auth project.

NTLM-over-HTTP is enough of a pain in the arse that it's usually better to use any other method of authentication available to you.

bobince
  • 528,062
  • 107
  • 651
  • 834
  • Can you help me with my question - http://stackoverflow.com/questions/25792274/ntlm-token-verification-in-java – JHS Sep 29 '14 at 11:26
2

You're receiving the Type 3 message, but you're not doing anything with it except printing out the details. You need to validate the client's response at this point and either send a 200 (if authorized) or a 401 (if not.)

However the Type 1 message you delivered is made up of static bytes and - while it will induce a client to send back a response - is mostly meaningless. It's not impossible to implement a complete NTLM authentication stack yourself, but the code you have will simply not work.

You could investigate an NTLM Solution for Java, or (assuming you're on Windows) you could call the necessary authentication functions like AcceptSecurityContext with JNI.

Edward Thomson
  • 74,857
  • 14
  • 158
  • 187
  • Edward, when you say: "you need to validate the client's response at this point" - what do you mean by that. How do i validate that. – Jasper Aug 07 '12 at 12:31
  • @Edward - Can you help me with my question - http://stackoverflow.com/questions/25792274/ntlm-token-verification-in-java – JHS Sep 29 '14 at 11:26