[jcifs] Cancel NTLM-Authentication Serverside

Tapperson Kevin Kevin.Tapperson at hcahealthcare.com
Fri Dec 17 13:57:34 GMT 2004


I have implemented a couple of things that could be used to get around this.
We have successfully used these in our jcifs based sso implementation for
our portal.

The first option is kind of a hack and I don't think it worked 100%
correctly in every situation.  (We are no longer using this, but it may suit
your needs or work for your situation.)  Change your filter such that on a
successful authentication it doesn't chain; remove the chain.doFilter()
call.  Replace the chain.doFilter() call with the following lines of code:

	StringBuffer URL = request.getRequestURL();
	if (request.getQueryString() != null)
	{
		URL.append("?" + request.getQueryString());
	}
	response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
	PrintWriter out = response.getWriter();
	out.println("<html>");
	out.println("<head>");
	out.println("<title>Portal Log In</title>");
	out.println("<script language=\"javascript\">");
	out.println("<!--");
	out.println("location.replace(\"" + URL.toString() + "\");");
	out.println("//-->");
	out.println("</script>");
	out.println("<noscript>");
	out.println("<meta http-equiv=\"Refresh\" content=\"0; URL=" +
URL.toString() + "\">");
	out.println("</noscript>");
	out.println("</head>");
	out.println("<body>");
	out.println("You were logged in successfully.  Click <a href=\"" +
URL.toString() + "\">here</a> to continue.");
	out.println("</body>");
	out.println("</html>");
	response.flushBuffer();
	return;

This will trick IE into thinking that the NTLM authentication failed.  It
actually sends the SC_UNAUTHORIZED HTTP return code, but also sends back an
HTML page with the response.  The page tries both a javascript redirect and
a meta refresh redirect to send the browser on to the correct destination
page.  If IE thinks that the NTLM authentication failed, it will not try to
re-authenticate via NTLM on each subsequent POST request.


The second option is to create another filter.  Here is the complete source
for our NTLMPostFilter:

import java.io.IOException;
import java.util.Enumeration;

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.Type1Message;
import jcifs.ntlmssp.Type2Message;
import jcifs.util.Base64;

public class NTLMPostFilter implements Filter
{
    public void init(FilterConfig filterConfig) throws ServletException
    {
    }

    public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
    {
        boolean pass = true;
        if (request instanceof HttpServletRequest)
        {
            HttpServletRequest httpRequest = (HttpServletRequest)request;
            if (httpRequest.getMethod().equals("POST"))
            {
                String msg = httpRequest.getHeader("Authorization");
                if ((msg != null) && (msg.startsWith("NTLM ")))
                {
                    /* decode the NTLM response from the client */
                    byte[] src = Base64.decode(msg.substring(5));

                    /* see if a type 1 message was sent by the client */
                    if (src[8] == 1)
                    {
                        HttpServletResponse httpResponse =
(HttpServletResponse)response;

                        Type1Message type1 = new Type1Message(src);

                        /* respond with a type 2 message */
                        Type2Message type2 = new Type2Message(type1, new
byte[8], null);
                        msg = Base64.encode(type2.toByteArray());
                        httpResponse.setHeader("WWW-Authenticate", "NTLM " +
msg);
 
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                        httpResponse.setContentLength(0);
                        httpResponse.flushBuffer();
                        pass = false;
                    }
                }
            }
        }

        if (pass)
        {
            chain.doFilter(request, response);
        }
    }

    public void destroy()
    {
    }
}

This filter works great.  It basically just entertains IE's attempt to
re-authenticate via NTLM prior to submitting POST data.  If a POST request
is received and it has an NTLM type 1 message in the Authorization header,
this filter rejects the request and sends back an NTLM type 2 message with
the SC_UNAUTHORIZED HTTP result code.  IE will then respond with the POST
data and send an NTLM type 3 message in the Authorization header.  This
filter just ignores the type 3 response, since IE coughs up the POST data at
that point.

Enjoy!
Kevin Tapperson


-----Original Message-----
From: Michael B Allen [mailto:mba2000 at ioplex.com]
Sent: Friday, December 17, 2004 3:19 AM
To: Ingo Rockel
Cc: jcifs at samba.org
Subject: Re: [jcifs] Cancel NTLM-Authentication Serverside


On Fri, 17 Dec 2004 09:54:19 +0100
Ingo Rockel <irockel at pironet-ndh.com> wrote:

> Hi all!
> 
> maybe someone has an idea concerning this. We have an application 
> running in an OracleAS application server, jcifs is configured as sso in 
> a filter. There also is a form-based login configured using a security 
> constraint in the application server. So if a client logs in, the 
> jcifs-ntlm-sso is called requesting ntlm-credentials, checking againt a
> DC.
> 
> Now the customer wants the login process to present the form based login 
> to be shown if the sso against the dc fails because the client is 
> unkown. First try was just to ignore the ntlm-login-fail and present the 
> form based login. But problem is in this case IE thinks NTLM-auth was 
> successfull and uses the NTLM header for all its requests. And the IE 
> seems to have a special behavior concerning post-requests (like a form 
> based login), it tries to reauthenticate the post request without 
> sending the post data, unfortuneately the app server has the mentioned 
> security constraint on this url and so again shows the form based login 
> and the client is trapped.
> 
> Any idea how to tell the IE silently to stop trying to send NTLM-creds 
> after first try failed.

Someone once claimed to have had some success with sending back some kind
of error that trick IE into thinking the session should be invalidated. I
don't think it was 403 as that will cause the Network Password Dialog
to pop up. Try googling for Eric Glass messages about this.

Or maybe someone else on the list has done this?

Mike

-- 
Greedo shoots first? Not in my Star Wars.


More information about the jcifs mailing list