[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
content-length
> 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[]
challenge)
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,
null);
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). */
resp.getWriter().println("");
/* skb */
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
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