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 + " ");
Terry Gardner
  • 10,957
  • 2
  • 28
  • 38
codeomnitrix
  • 4,179
  • 19
  • 66
  • 102
  • i'm confused, you want to authenticate the user twice (with ldap _and_ ntlm)? – jtahlborn Jul 03 '13 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 – codeomnitrix Jul 03 '13 at 14:55
  • Consider an existing implementation of NTLM: http://stackoverflow.com/questions/15020734/using-ntlm-authentication-in-java-applications . – Joe Sep 28 '13 at 13:56
  • @codeomnitrix I believe all you need to do is configure Firefox to use NTLM authentication!!! – Amr Gawish Oct 03 '13 at 00:56

3 Answers3

2

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.

GeertPt
  • 16,398
  • 2
  • 37
  • 61
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

Community
  • 1
  • 1
Nils
  • 1,750
  • 14
  • 10
0

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

Amr Gawish
  • 2,015
  • 1
  • 17
  • 29