[jcifs] Cancel NTLM-Authentication Serverside

Ingo Rockel irockel at pironet-ndh.com
Thu Dec 23 09:37:18 GMT 2004


Hi Kevin,

unfortuneately because of the strange handling of the security 
constraint in oracleAS, both solutions don't work out of the box (I had 
a check to prevent the auth stuff to be done again, but unfortuneately 
the IE didn't stop to reauthenticate post requests and the filter 
solution didn't work this way because with this special 
form-based-login-post request no filter is called.

But I could convince the customer to just use SSO with http and 
form-based with https, so more need to use the hack...

But again thanks a lot for the help :o).

Happy Christmas,

	Ingo

Tapperson Kevin schrieb:
> Ingo,
> 
> In order to prevent the endless looping, you may need to implement some
> checking prior to initiating the NTLM authentication process on the server
> side.
> 
> For example, here's some pseudo code to use in your customized filter:
> 
> String user = (String)session.getAttribute("user");
> if (user != null)
> {
> 	/* a user is already logged in; bypass NTLM and use the user saved
> in session */
> 	chain.doFilter();
> }
> else
> {
> 	/* a user has not been logged in yet; try NTLM now */
> 	// do the NTLM authentication process now
> 	// if (msg == type 1)
> 	// {
> 	//	send type 2
> 	// }
> 	// else if (msg == type 3)
> 	// {
> 	// 	try the smb login
> 	//	if (smb login was successful)
> 	//	{
> 	//		session.setAttribute("user", type3.getDomain() +
> "\\" + type3.getUsername());
> 	
> response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
> 	//		redirect user to the appropriate destination page
> (see code below); don't do chain.doFilter()
> 	//	}
> 	// }
> }
> 
> Likewise, you may also need to add a similar variable to be tracked in
> session to prevent looping in the event that the NTLM authentication fails.
> Basically, you would only want to try the NTLM authentication once and
> re-direct the user to an error page or form based login page if the NTLM
> process failed; otherwise, your user object in session would always be null
> and it would loop there as well.
> 
> It may also be useful to install and use something like ethereal
> (http://www.ethereal.com).  It can give you a packet trace of all requests
> made by the client to your application server.  It makes it easier to
> analyze what is going on.
> 
> Hope this helps...
> 
> Kevin Tapperson
> kevin.tapperson at ehc.com
> 
> -----Original Message-----
> From: Ingo Rockel [mailto:irockel at pironet-ndh.com]
> Sent: Friday, December 17, 2004 10:31 AM
> To: Tapperson Kevin
> Subject: Re: [jcifs] Cancel NTLM-Authentication Serverside
> 
> 
> Thanx a lot for the information. Unfortuneately the second solution 
> doesn't work in this context, the security constraint is resolved before 
> any filter is called :(... I wasn't able to get the first solution to 
> work. Although I send this response to the client (without chaining any 
> further), the IE still sends NTLM with the next request and the is 
> caught in an endless loop, as the redirect is send again.
> 
> Any idea what I might have done wrong?
> 
> Thanx for the help,
> 
> 	Ingo
> 
> Tapperson Kevin schrieb:
> 
>>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
>>
> 
> 
> 


-- 
PIRONET NDH AG
Ingo Rockel - Produktentwicklung
Maarweg 149-161, 50825 Koeln
Tel.: +49 (0)221-770-1788 / Fax: +49 (0)221-770-1005
mailto:irockel at pironet-ndh.com - http://www.pironet-ndh.com


More information about the jcifs mailing list