[jcifs] Empty POST requests on IE

Asaf Mesika asaf.mesika at gmail.com
Thu Feb 7 12:16:39 GMT 2008


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.
-------------- next part --------------
HTML attachment scrubbed and removed


More information about the jcifs mailing list