[jcifs] Empty POST requests on IE

Michael B Allen miallen at ioplex.com
Thu Feb 7 15:33:39 GMT 2008


Note that I just updated the NTLM doc regarding this. There's a registry
key that will disable this behavior in IE.

Mike

On Thu, 7 Feb 2008 14:16:39 +0200
"Asaf Mesika" <asaf.mesika at gmail.com> wrote:

> Hi guys,
> 
> I came across a well known problem in jCIFS NtlmHttpFilter.
> 
> *The problem
> *POST requests are sent without parameters, and with a type-1 ntlm message
> in the authorization header.
> I Googled and found out that many people patched the filter locally, or
> simply created another filter of their own to handle this specific problem
> (See message I found and pasted below
> 
> *The question
> *Is there any reason why no one patched NtlmHttpFilter to handle empty POST
> requests with Authorization header filled with type-1 message? It can easily
> be fixed.
> 
> 
> *Email reference* - describing the problem and solution, from Dec 2004
> [jcifs] Cancel NTLM-Authentication Serverside *Tapperson Kevin* Kevin.Tapperson
> at hcahealthcare.com
> <jcifs%40lists.samba.org?Subject=%5Bjcifs%5D%20Cancel%20NTLM-Authentication%20Serverside&In-Reply-To=>
> *Fri Dec 17 13:57:34 GMT 2004*
> 
>    - Previous message: [jcifs] Jcifs on Java 1.3.1
>    <http://lists.samba.org/archive/jcifs/2004-December/004458.html>
>    - Next message: [jcifs] Re: JCIFS Ext
>    <http://lists.samba.org/archive/jcifs/2004-December/004462.html>
>    - *Messages sorted by:* [ date
> ]<http://lists.samba.org/archive/jcifs/2004-December/date.html#4459> [
>    thread ]<http://lists.samba.org/archive/jcifs/2004-December/thread.html#4459>
> [
>    subject ]<http://lists.samba.org/archive/jcifs/2004-December/subject.html#4459>
> [
>    author ]<http://lists.samba.org/archive/jcifs/2004-December/author.html#4459>
> 
> ------------------------------
> 
> 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
> <https://lists.samba.org/mailman/listinfo/jcifs>]
> Sent: Friday, December 17, 2004 3:19 AM
> To: Ingo Rockel
> Cc: jcifs at samba.org <https://lists.samba.org/mailman/listinfo/jcifs>
> Subject: Re: [jcifs] Cancel NTLM-Authentication Serverside
> 
> 
> On Fri, 17 Dec 2004 09:54:19 +0100
> Ingo Rockel <irockel at pironet-ndh.com
> <https://lists.samba.org/mailman/listinfo/jcifs>> 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.
> 


-- 
Michael B Allen
PHP Active Directory SPNEGO SSO
http://www.ioplex.com/


More information about the jcifs mailing list