[jcifs] RE: HTTP 1.1 protocol errors with jcifs 0.8.0b (jcifs.http.NtlmSs p.java)

Steven Beal steven.beal at peregrine.com
Wed Jan 28 16:54:17 GMT 2004

> In short, I could not use jCIFS 0.8.0b with Tomcat 4.1.24 via
> IIS (isapi_redirector2.dll) or Apache (mod_jk).  
> The only way I could get the library to work as advertised was
> via Tomcat's built in webserver.  The error was traced
> to jcifs.http.NtlmSsp.java (see below). The authenticate() method
> sets the content-length of the response to 0.  Tomcat's internal http 
> server tolerates this and sends no body in the response but the other 
> configurations send the configured message (html) associated with the 
> response code as the body.  With a non zero length body, the
> value of 0 creates protocol errors and prevents the authentication
> from succeeding.  This error mainifests itself as garbled html mixed 
> with HTTP response headers displayed in the browser.
> Experimentation showed that when using IIS, the content-length
> must be zero or IIS will send Connection:close and disrupt the NTCR
> authentication.  This requires that the body of the response be
> zero length.  
> The modified authenticate() method below corrects the problem.
> Please see the comments marked with "skb".
> It is unfortunate to have to send a zero length body, but I can
> see no other solution since the container cannot be allowed to
> respond with the message associated with the response code.
> There is no way to reliably determine the correct content length of such 
> a response, especially since the message is configurable.
> BTW - Many thanks for such a great utility.  
> -Steve Beal

     * Performs NTLM authentication for the servlet request.
     * @param req The request being serviced.
     * @param resp The response.
     * @param challenge The domain controller challenge.
     * @throws IOException If an IO error occurs.
     * @throws ServletException If an error occurs.
    public static NtlmPasswordAuthentication authenticate(
            HttpServletRequest req, HttpServletResponse resp, byte[]
                    throws IOException, ServletException {
        String msg = req.getHeader("Authorization");
        if (msg != null && msg.startsWith("NTLM ")) {
            byte[] src = Base64.decode(msg.substring(5));
            if (src[8] == 1) {
                Type1Message type1 = new Type1Message(src);
                Type2Message type2 = new Type2Message(type1, challenge,
                msg = Base64.encode(type2.toByteArray());
                resp.setHeader( "WWW-Authenticate", "NTLM " + msg );
	/* skb - probably not needed but it can't hurt. */
                resp.setHeader( "Connection", "Keep-Alive" );
	/* skb */
            } else if (src[8] == 3) {
                Type3Message type3 = new Type3Message(src);
                byte[] lmResponse = type3.getLMResponse();
                if (lmResponse == null) lmResponse = new byte[0];
                byte[] ntResponse = type3.getNTResponse();
                if (ntResponse == null) ntResponse = new byte[0];
                return new NtlmPasswordAuthentication(type3.getDomain(),
                        type3.getUser(), lmResponse, ntResponse);
        } else {
            resp.setHeader("WWW-Authenticate", "NTLM");
            resp.setHeader("Connection", "close");
	/* skb */
	/* Tomcat 4.1.24 wants this, or the default page associated 
	 * with the status code is written to the response rendering 
	 * the content-length header invalid and the data on the
	 * persistent stream corrupt. Note that this is not needed
	 * when using Tomcat's built in webserver (different code path). */
	/* skb */
	resp.setContentLength( 0 ); 
	/* skb - setContentLength(0) is required by IIS or it will set 
	 * Connection:close in the response and hose up the NTCR protocol.

        resp.flushBuffer(); /* skb - commits the buffer */
        return null;

More information about the jcifs mailing list