3

I was reading this article, with the help of it I am able to find the username, domain name and hostname of the machine accessing my JSP Page, But Still I can't understand how to authenticate the user. Because in Firefox when I am accessing my JSP page and try to enter correct Username but wrong password, it authenticates the user.

So the prime concern is how can I authenticate the user with NTLM Protocol, i.e. once I have the username and password, I can make a LDAP request to authenticate the user, but here only Username of the person is known to server.

<%

String auth = request.getHeader("Authorization");
/*
 * Client to Server - Get Page.
 */
if (auth == null) {

    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    response.setHeader("WWW-Authenticate", "NTLM");
    return;
}
/*
 * Client to Server 
 GET ...
 Authorization: NTLM <base64-encoded type-1-message>

Type 1 Message - 
        0       1       2       3
        +-------+-------+-------+-------+
    0:  |  'N'  |  'T'  |  'L'  |  'M'  |
        +-------+-------+-------+-------+
    4:  |  'S'  |  'S'  |  'P'  |   0   |
        +-------+-------+-------+-------+
    8:  |   1   |   0   |   0   |   0   |
        +-------+-------+-------+-------+
    12:  | 0x03  | 0xb2  |   0   |   0   |
        +-------+-------+-------+-------+
    16:  | domain length | domain length |
        +-------+-------+-------+-------+
    20:  | domain offset |   0   |   0   |
        +-------+-------+-------+-------+
    24:  |  host length  |  host length  |
        +-------+-------+-------+-------+
    28:  |  host offset  |   0   |   0   |
        +-------+-------+-------+-------+
    32:  |  host string                  |
        +                               +
        .                               .
        .                               .
        +             +-----------------+
        |             | domain string   |
        +-------------+                 +
        .                               .
        .                               .
        +-------+-------+-------+-------+
 */
if (auth.startsWith("NTLM ")) {



    byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth
            .substring(5));
    int off = 0, length, offset;
    String s;
    s = new String(msg, 0, msg.length);

    if (msg[8] == 1) {

        off = 18;

        byte z = 0;
        /*
                    0       1       2       3
         +-------+-------+-------+-------+
     0:  |  'N'  |  'T'  |  'L'  |  'M'  |
         +-------+-------+-------+-------+
     4:  |  'S'  |  'S'  |  'P'  |   0   |
         +-------+-------+-------+-------+
     8:  |   2   |   0   |   0   |   0   |
         +-------+-------+-------+-------+
    12:  |   0   |   0   |   0   |   0   |
         +-------+-------+-------+-------+
    16:  |  message len  |   0   |   0   |
         +-------+-------+-------+-------+
    20:  | 0x01  | 0x82  |   0   |   0   |
         +-------+-------+-------+-------+
    24:  |                               |
         +          server nonce         |
    28:  |                               |
         +-------+-------+-------+-------+
    32:  |   0   |   0   |   0   |   0   |
         +-------+-------+-------+-------+
    36:  |   0   |   0   |   0   |   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, 
                        (byte) 1, (byte) 9, (byte) 0, (byte) 9, 
                        (byte) 1, (byte) 9, (byte) 8, (byte) 9,  
                        z, z, z, z, 
                        z, z, z, z };
        // 
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setHeader("WWW-Authenticate", "NTLM "
                + new sun.misc.BASE64Encoder().encodeBuffer(msg1)
                        .trim());
        return;
    } 
    /*
     * Client sending type 3 message.

        0       1       2       3
        +-------+-------+-------+-------+
    0:  |  'N'  |  'T'  |  'L'  |  'M'  |
        +-------+-------+-------+-------+
    4:  |  'S'  |  'S'  |  'P'  |   0   |
        +-------+-------+-------+-------+
    8:  |   3   |   0   |   0   |   0   |
        +-------+-------+-------+-------+
   12:  |  LM-resp len  |  LM-Resp len  |
        +-------+-------+-------+-------+
   16:  |  LM-resp off  |   0   |   0   |
        +-------+-------+-------+-------+
   20:  |  NT-resp len  |  NT-Resp len  |
        +-------+-------+-------+-------+
   24:  |  NT-resp off  |   0   |   0   |
        +-------+-------+-------+-------+
   28:  | domain length | domain length |
        +-------+-------+-------+-------+
   32:  | domain offset |   0   |   0   |
        +-------+-------+-------+-------+
   36:  |  user length  |  user length  |
        +-------+-------+-------+-------+
   40:  |  user offset  |   0   |   0   |
        +-------+-------+-------+-------+
   44:  |  host length  |  host length  |
        +-------+-------+-------+-------+
   48:  |  host offset  |   0   |   0   |
        +-------+-------+-------+-------+
   52:  |   0   |   0   |   0   |   0   |
        +-------+-------+-------+-------+
   56:  |  message len  |   0   |   0   |
        +-------+-------+-------+-------+
   60:  | 0x01  | 0x82  |   0   |   0   |
        +-------+-------+-------+-------+
   64:  | domain string                 |
        +                               +
        .                               .
        .                               .
        +           +-------------------+
        |           | user string       |
        +-----------+                   +
        .                               .
        .                               .
        +                 +-------------+
        |                 | host string |
        +-----------------+             +
        .                               .
        .                               .
        +   +---------------------------+
        |   | LanManager-response       |
        +---+                           +
        .                               .
        .                               .
        +            +------------------+
        |            | NT-response      |
        +------------+                  +
        .                               .
        .                               .
        +-------+-------+-------+-------+
     */
    else if (msg[8] == 3) {

        off = 30;
        length = msg[off + 17] * 256 + msg[off + 16];
        offset = msg[off + 19] * 256 + msg[off + 18];

        s = new String(msg, offset, length);

        System.out.println("Host String - " + s + " ");
    } else{

        return;
    }
    /*
     * Reading domain information
     */
    length = msg[off + 1] * 256 + msg[off];
    offset = msg[off + 3] * 256 + msg[off + 2];     
    s = new String(msg, offset, length);
    System.out.println("Domain Name - " + s +  " ");

    /*
     * Reading User Name information.
     */
    length = msg[off + 9] * 256 + msg[off + 8];
    offset = msg[off + 11] * 256 + msg[off + 10];

    s = new String(msg, offset, length);
    System.out.println("User Name - " + s + " ");
4
  • i'm confused, you want to authenticate the user twice (with ldap and ntlm)? Commented Jul 3, 2013 at 11:46
  • No, You see when I am running this page in firefox, it prompts me to enter my credentials, but on this page even if I enter only user name it accepts, it doesn't check password against the Active Directory Commented Jul 3, 2013 at 14:55
  • Consider an existing implementation of NTLM: stackoverflow.com/questions/15020734/… . Commented Sep 28, 2013 at 13:56
  • @codeomnitrix I believe all you need to do is configure Firefox to use NTLM authentication!!! Commented Oct 3, 2013 at 0:56

3 Answers 3

2
+50

NTLM authentication does not use a password, it uses a challenge-response protocol which requires a few server roundtrips.

In the second GET request, you respond with a server 'nonce' which is the authentication challenge received from the domain controller. On the third GET, you get the authentication response which you can validate with the challenge via the domain controller.

In your code, you use a hard-coded challenge (0x19091989), and completely ignore the response.

JCIFS has an implementation that actually finds a domain controller to handle the challenge and response in http://code.google.com/p/jcifs-fork/source/browse/trunk/jcifs/src/jcifs/http/NtlmHttpFilter.java. You could reverse engineer this, or use the filter 'an sich' as described in http://jcifs.samba.org/src/docs/ntlmhttpauth.html. AFAIK this only works on a Windows server, but I could be mistaken.

Sign up to request clarification or add additional context in comments.

Comments

1

In the following thread they put the Tomcat behind an Apache Server and use an Apache Module to perform the NTLM authentication.

Spring 3 and NTLM authentication

Comments

0

All you have to do is to follow this article to enable Firefox to use NTLM like IE and Chrome does!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.