You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2014/08/12 12:53:23 UTC

svn commit: r1617447 - in /tomcat/tc7.0.x/trunk: ./ java/org/apache/catalina/authenticator/ test/org/apache/tomcat/util/net/ webapps/docs/

Author: markt
Date: Tue Aug 12 10:53:23 2014
New Revision: 1617447

URL: http://svn.apache.org/r1617447
Log:
Enable pre-emptive authentication to work with the SSL authenticator. Based on a patch by jlmonteiro.

Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java
    tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/net/TestClientCert.java
    tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/net/TesterSupport.java
    tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
  Merged /tomcat/trunk:r1617445

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java?rev=1617447&r1=1617446&r2=1617447&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java Tue Aug 12 10:53:23 2014
@@ -47,6 +47,7 @@ import org.apache.catalina.deploy.Securi
 import org.apache.catalina.util.DateTool;
 import org.apache.catalina.util.SessionIdGenerator;
 import org.apache.catalina.valves.ValveBase;
+import org.apache.coyote.ActionCode;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.res.StringManager;
@@ -561,8 +562,7 @@ public abstract class AuthenticatorBase 
         }
 
         if (!authRequired && context.getPreemptiveAuthentication()) {
-            X509Certificate[] certs = (X509Certificate[]) request.getAttribute(
-                    Globals.CERTIFICATES_ATTR);
+            X509Certificate[] certs = getRequestCertificates(request);
             authRequired = certs != null && certs.length > 0;
         }
 
@@ -614,6 +614,35 @@ public abstract class AuthenticatorBase 
 
     // ------------------------------------------------------ Protected Methods
 
+    /**
+     * Look for the X509 certificate chain in the Request under the key
+     * <code>javax.servlet.request.X509Certificate</code>. If not found, trigger
+     * extracting the certificate chain from the Coyote request.
+     *
+     * @param request   Request to be processed
+     *
+     * @return          The X509 certificate chain if found, <code>null</code>
+     *                  otherwise.
+     */
+    protected X509Certificate[] getRequestCertificates(final Request request)
+            throws IllegalStateException {
+
+        X509Certificate certs[] =
+                (X509Certificate[]) request.getAttribute(Globals.CERTIFICATES_ATTR);
+
+        if ((certs == null) || (certs.length < 1)) {
+            try {
+                request.getCoyoteRequest().action (ActionCode.REQ_SSL_CERTIFICATE, null);
+                certs = (X509Certificate[]) request.getAttribute(Globals.CERTIFICATES_ATTR);
+            } catch (IllegalStateException ise) {
+                // Request body was too large for save buffer
+                // Return null which will trigger an auth failure
+            }
+        }
+
+        return certs;
+    }
+
 
     /**
      * Associate the specified single sign on identifier with the

Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java?rev=1617447&r1=1617446&r2=1617447&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/authenticator/SSLAuthenticator.java Tue Aug 12 10:53:23 2014
@@ -26,10 +26,8 @@ import java.security.cert.X509Certificat
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.catalina.Globals;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.deploy.LoginConfig;
-import org.apache.coyote.ActionCode;
 
 
 
@@ -129,27 +127,14 @@ public class SSLAuthenticator
         if (containerLog.isDebugEnabled())
             containerLog.debug(" Looking up certificates");
 
-        X509Certificate certs[] = (X509Certificate[])
-            request.getAttribute(Globals.CERTIFICATES_ATTR);
-        if ((certs == null) || (certs.length < 1)) {
-            try {
-                request.getCoyoteRequest().action
-                                  (ActionCode.REQ_SSL_CERTIFICATE, null);
-            } catch (IllegalStateException ise) {
-                // Request body was too large for save buffer
-                response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
-                        sm.getString("authenticator.certificates"));
-                return false;
-            }
-            certs = (X509Certificate[])
-                request.getAttribute(Globals.CERTIFICATES_ATTR);
-        }
+        X509Certificate certs[] = getRequestCertificates(request);
+
         if ((certs == null) || (certs.length < 1)) {
             if (containerLog.isDebugEnabled())
                 containerLog.debug("  No certificates included with this request");
             response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
-                               sm.getString("authenticator.certificates"));
-            return (false);
+                    sm.getString("authenticator.certificates"));
+            return false;
         }
 
         // Authenticate the specified certificate chain

Modified: tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/net/TestClientCert.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/net/TestClientCert.java?rev=1617447&r1=1617446&r2=1617447&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/net/TestClientCert.java (original)
+++ tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/net/TestClientCert.java Tue Aug 12 10:53:23 2014
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertEqu
 import org.junit.Assume;
 import org.junit.Test;
 
+import org.apache.catalina.Context;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.catalina.startup.TomcatBaseTest;
 import org.apache.tomcat.util.buf.ByteChunk;
@@ -35,18 +36,37 @@ import org.apache.tomcat.util.buf.ByteCh
 public class TestClientCert extends TomcatBaseTest {
 
     @Test
-    public void testClientCertGet() throws Exception {
+    public void testClientCertGetWithoutPreemptive() throws Exception {
+        doTestClientCertGet(false);
+    }
+
+    @Test
+    public void testClientCertGetWithPreemptive() throws Exception {
+        doTestClientCertGet(true);
+    }
+
+    public void doTestClientCertGet(boolean preemtive) throws Exception {
         Assume.assumeTrue("SSL renegotiation has to be supported for this test",
                 TesterSupport.isRenegotiationSupported(getTomcatInstance()));
 
+        if (preemtive) {
+            // Only one context deployed
+            Context c = (Context) getTomcatInstance().getHost().findChildren()[0];
+            c.setPreemptiveAuthentication(true);
+        }
+
         // Unprotected resource
         ByteChunk res =
                 getUrl("https://localhost:" + getPort() + "/unprotected");
-        assertEquals("OK", res.toString());
+        if (preemtive) {
+            assertEquals("OK-" + TesterSupport.ROLE, res.toString());
+        } else {
+            assertEquals("OK", res.toString());
+        }
 
         // Protected resource
         res = getUrl("https://localhost:" + getPort() + "/protected");
-        assertEquals("OK", res.toString());
+        assertEquals("OK-" + TesterSupport.ROLE, res.toString());
     }
 
     @Test

Modified: tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/net/TesterSupport.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/net/TesterSupport.java?rev=1617447&r1=1617446&r2=1617447&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/net/TesterSupport.java (original)
+++ tomcat/tc7.0.x/trunk/test/org/apache/tomcat/util/net/TesterSupport.java Tue Aug 12 10:53:23 2014
@@ -54,6 +54,8 @@ import org.apache.catalina.startup.Tomca
 
 public final class TesterSupport {
 
+    public static final String ROLE = "testrole";
+
     protected static final boolean RFC_5746_SUPPORTED;
 
     static {
@@ -210,14 +212,14 @@ public final class TesterSupport {
         SecurityCollection collection = new SecurityCollection();
         collection.addPattern("/protected");
         SecurityConstraint sc = new SecurityConstraint();
-        sc.addAuthRole("testrole");
+        sc.addAuthRole(ROLE);
         sc.addCollection(collection);
         ctx.addConstraint(sc);
 
         // Configure the Realm
         MapRealm realm = new MapRealm();
         realm.addUser("CN=user1, C=US", "not used");
-        realm.addUserRole("CN=user1, C=US", "testrole");
+        realm.addUserRole("CN=user1, C=US", ROLE);
         ctx.setRealm(realm);
 
         // Configure the authenticator
@@ -238,6 +240,9 @@ public final class TesterSupport {
                 throws ServletException, IOException {
             resp.setContentType("text/plain");
             resp.getWriter().print("OK");
+            if (req.isUserInRole(ROLE)) {
+                resp.getWriter().print("-" + ROLE);
+            }
         }
 
         @Override

Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1617447&r1=1617446&r2=1617447&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Tue Aug 12 10:53:23 2014
@@ -88,6 +88,10 @@
         <bug>56796</bug>: Remove unnecessary sleep when stopping a web
         application. (markt)
       </fix>
+      <fix>
+        <bug>56825</bug>: Enable pre-emptive authentication to work with the
+        SSL authenticator. Based on a patch by jlmonteiro. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">



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