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: [email protected]
For additional commands, e-mail: [email protected]