Author: markt
Date: Sun Aug 22 21:02:33 2010
New Revision: 987948

URL: http://svn.apache.org/viewvc?rev=987948&view=rev
Log:
Provide 100 Continue responses if required during FORM authentication
Side issues from investigating 
https://issues.apache.org/bugzilla/show_bug.cgi?id=49779

Added:
    tomcat/trunk/test/org/apache/catalina/authenticator/
    
tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java  
 (with props)
Modified:
    tomcat/trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java
    tomcat/trunk/webapps/docs/changelog.xml

Modified: 
tomcat/trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java?rev=987948&r1=987947&r2=987948&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/authenticator/FormAuthenticator.java 
Sun Aug 22 21:02:33 2010
@@ -246,8 +246,9 @@ public class FormAuthenticator
             return (false);
         }
 
-        // Yes -- Validate the specified credentials and redirect
-        // to the error page if they are not correct
+        // Yes -- Acknowledge the request, validate the specified credentials
+        // and redirect to the error page if they are not correct
+        request.getResponse().sendAcknowledgement();
         Realm realm = context.getRealm();
         if (characterEncoding != null) {
             request.setCharacterEncoding(characterEncoding);
@@ -511,6 +512,9 @@ public class FormAuthenticator
         }
 
         if ("POST".equalsIgnoreCase(request.getMethod())) {
+            // May need to acknowledge a 100-continue expectation
+            request.getResponse().sendAcknowledgement();
+
             ByteChunk body = new ByteChunk();
             body.setLimit(request.getConnector().getMaxSavePostSize());
 

Added: 
tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java?rev=987948&view=auto
==============================================================================
--- 
tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java 
(added)
+++ 
tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java 
Sun Aug 22 21:02:33 2010
@@ -0,0 +1,159 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.catalina.authenticator;
+
+import java.io.File;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.startup.SimpleHttpClient;
+import org.apache.catalina.startup.TestTomcat.MapRealm;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+
+public class TestFormAuthenticator extends TomcatBaseTest {
+
+    public void testBug49779() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+        File appDir = new File(getBuildDirectory(), "webapps/examples");
+        Context ctx =
+            tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath());
+        
+        MapRealm realm = new MapRealm();
+        realm.addUser("tomcat", "tomcat");
+        realm.addUserRole("tomcat", "tomcat");
+        ctx.setRealm(realm);
+
+        tomcat.start();
+
+        Bug49779ClientStage1 client = new Bug49779ClientStage1();
+        client.setPort(getPort());
+        
+        // First request for authenticated resource 
+        Exception e = client.doRequest(null);
+        assertNull(e);
+        assertTrue(client.isResponse200());
+        assertTrue(client.isResponseBodyOK());
+        
+        String sessionID = client.getSessionId();
+        
+        // Second request for the login page
+        client.reset();
+        e = client.doRequest(sessionID);
+        assertNull(e);
+        assertTrue(client.isResponse302());
+        assertTrue(client.isResponseBodyOK());
+
+        // Third request - follow the redirect
+        client.reset();
+        e = client.doRequest(sessionID);
+        assertNull(e);
+        assertTrue(client.isResponse200());
+        assertTrue(client.isResponseBodyOK());
+
+        // Session ID changes after successful authentication
+        sessionID = client.getSessionId();
+
+        // Subsequent requests - direct to the resource
+        for (int i = 0; i < 5; i++) {
+            client.reset();
+            e = client.doRequest(sessionID);
+            assertNull(e);
+            assertTrue(client.isResponse200());
+            assertTrue(client.isResponseBodyOK());
+        }
+    }
+    
+    private final class Bug49779ClientStage1 extends SimpleHttpClient {
+
+        private int requestCount = 0;
+
+        private Exception doRequest(String sessionId) {
+            try {
+                String request[] = new String[2];
+                if (requestCount == 1) {
+                    request[0] =
+                            "POST 
/examples/jsp/security/protected/j_security_check HTTP/1.1" + CRLF;
+                } else if (requestCount == 2) {
+                    request[0] =
+                            "GET /examples/jsp/security/protected/index.jsp 
HTTP/1.1" + CRLF;
+                } else {
+                    request[0] =
+                            "POST /examples/jsp/security/protected/index.jsp 
HTTP/1.1" + CRLF;
+                }
+
+                request[0] = request[0] + 
+                        "Host: localhost" + CRLF +
+                        "Expect: 100-continue" + CRLF +
+                        "Connection: close" + CRLF;
+                
+                if (sessionId != null) {
+                    request[0] = request[0] +
+                            "Cookie: JSESSIONID=" + sessionId + CRLF;
+                }
+                
+                if (requestCount == 1) {
+                    request[0] = request[0] +
+                            "Content-Type: application/x-www-form-urlencoded" 
+ CRLF +
+                            "Content-length: 35" + CRLF +
+                            CRLF;
+                    request[1] = "j_username=tomcat&j_password=tomcat";
+                } else if (requestCount ==2) {
+                    request[1] = CRLF;
+                } else {
+                    request[0] = request[0] +
+                            "Content-Type: application/x-www-form-urlencoded" 
+ CRLF +
+                            "Content-length: 7" + CRLF +
+                            CRLF;
+                    request[1] = "foo=bar";
+                }
+
+                setRequest(request);
+                if (requestCount != 2) {
+                    setUseContinue(true);
+                }
+                
+                connect();
+                processRequest();
+                disconnect();
+                
+                requestCount++;
+            } catch (Exception e) {
+                e.printStackTrace();
+                return e;
+            }
+            return null;
+        }
+
+        @Override
+        public boolean isResponseBodyOK() {
+            String expected;
+            
+            if (requestCount == 1) {
+                // First request should result in the login page
+                expected = "<title>Login Page for Examples</title>";
+            } else if (requestCount == 2) {
+                // Second request should result in a redirect
+                return true;
+            } else {
+                // Subsequent requests should result in the protected page 
+                expected = "<title>Protected Page for Examples</title>";
+            }
+            return getResponseBody().contains(expected);
+        }
+        
+    }
+}

Propchange: 
tomcat/trunk/test/org/apache/catalina/authenticator/TestFormAuthenticator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=987948&r1=987947&r2=987948&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Sun Aug 22 21:02:33 2010
@@ -50,6 +50,10 @@
         <bug>49757</bug>: Correct some generics warnings. Based on a patch
         provided by Gábor. (markt)
       </fix>
+      <fix>
+        Provide 100 Continue responses at appropriate points during FORM
+        authentication if client indicates that they are expected. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to