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 2011/04/01 12:49:44 UTC

svn commit: r1087643 - in /tomcat/trunk: java/org/apache/catalina/ java/org/apache/catalina/authenticator/ java/org/apache/catalina/core/ java/org/apache/catalina/startup/ test/org/apache/catalina/core/ test/webapp-3.0-servletsecurity2/ test/webapp-3.0...

Author: markt
Date: Fri Apr  1 10:49:43 2011
New Revision: 1087643

URL: http://svn.apache.org/viewvc?rev=1087643&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=12428
Add optional support for preemptive authentication on a per context basis
Based on a patch suggested by Werner Donn

Added:
    tomcat/trunk/test/webapp-3.0-servletsecurity2/
    tomcat/trunk/test/webapp-3.0-servletsecurity2/WEB-INF/
    tomcat/trunk/test/webapp-3.0-servletsecurity2/WEB-INF/web.xml   (with props)
    tomcat/trunk/test/webapp-3.0-servletsecurity2/protected.jsp   (with props)
    tomcat/trunk/test/webapp-3.0-servletsecurity2/unprotected.jsp   (with props)
Modified:
    tomcat/trunk/java/org/apache/catalina/Context.java
    tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java
    tomcat/trunk/test/org/apache/catalina/core/TestStandardWrapper.java
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/docs/config/context.xml

Modified: tomcat/trunk/java/org/apache/catalina/Context.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Context.java?rev=1087643&r1=1087642&r2=1087643&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/Context.java (original)
+++ tomcat/trunk/java/org/apache/catalina/Context.java Fri Apr  1 10:49:43 2011
@@ -1349,5 +1349,18 @@ public interface Context extends Contain
      */
     public boolean getFireRequestListenersOnForwards();
     
+    /**
+     * Configures if a user presents authentication credentials, whether the
+     * context will process them when the request is for a non-protected
+     * resource.
+     */
+    public void setPreemptiveAuthentication(boolean enable);
+
+    /**
+     * Determines if a user presents authentication credentials, will the
+     * context will process them when the request is for a non-protected
+     * resource.
+     */
+    public boolean getPreemptiveAuthentication();
 }
 

Modified: tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java?rev=1087643&r1=1087642&r2=1087643&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java (original)
+++ tomcat/trunk/java/org/apache/catalina/authenticator/AuthenticatorBase.java Fri Apr  1 10:49:43 2011
@@ -21,6 +21,7 @@ package org.apache.catalina.authenticato
 
 import java.io.IOException;
 import java.security.Principal;
+import java.security.cert.X509Certificate;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Locale;
@@ -32,6 +33,7 @@ import javax.servlet.http.HttpServletRes
 import org.apache.catalina.Authenticator;
 import org.apache.catalina.Container;
 import org.apache.catalina.Context;
+import org.apache.catalina.Globals;
 import org.apache.catalina.LifecycleException;
 import org.apache.catalina.Manager;
 import org.apache.catalina.Realm;
@@ -454,8 +456,7 @@ public abstract class AuthenticatorBase 
         SecurityConstraint [] constraints
             = realm.findSecurityConstraints(request, this.context);
        
-        if ((constraints == null) /* &&
-            (!Constants.FORM_METHOD.equals(config.getAuthMethod())) */ ) {
+        if (constraints == null && !context.getPreemptiveAuthentication()) {
             if (log.isDebugEnabled())
                 log.debug(" Not subject to any constraint");
             getNext().invoke(request, response);
@@ -464,7 +465,7 @@ public abstract class AuthenticatorBase 
 
         // Make sure that constrained resources are not cached by web proxies
         // or browsers as caching can provide a security hole
-        if (disableProxyCaching && 
+        if (constraints != null && disableProxyCaching && 
             // FIXME: Disabled for Mozilla FORM support over SSL 
             // (improper caching issue)
             //!request.isSecure() &&
@@ -482,36 +483,55 @@ public abstract class AuthenticatorBase 
         }
 
         int i;
-        // Enforce any user data constraint for this security constraint
-        if (log.isDebugEnabled()) {
-            log.debug(" Calling hasUserDataPermission()");
-        }
-        if (!realm.hasUserDataPermission(request, response,
-                                         constraints)) {
+        if (constraints != null) {
+            // Enforce any user data constraint for this security constraint
             if (log.isDebugEnabled()) {
-                log.debug(" Failed hasUserDataPermission() test");
+                log.debug(" Calling hasUserDataPermission()");
+            }
+            if (!realm.hasUserDataPermission(request, response,
+                                             constraints)) {
+                if (log.isDebugEnabled()) {
+                    log.debug(" Failed hasUserDataPermission() test");
+                }
+                /*
+                 * ASSERT: Authenticator already set the appropriate
+                 * HTTP status code, so we do not have to do anything special
+                 */
+                return;
             }
-            /*
-             * ASSERT: Authenticator already set the appropriate
-             * HTTP status code, so we do not have to do anything special
-             */
-            return;
         }
 
         // Since authenticate modifies the response on failure,
         // we have to check for allow-from-all first.
-        boolean authRequired = true;
-        for(i=0; i < constraints.length && authRequired; i++) {
-            if(!constraints[i].getAuthConstraint()) {
-                authRequired = false;
-            } else if(!constraints[i].getAllRoles()) {
-                String [] roles = constraints[i].findAuthRoles();
-                if(roles == null || roles.length == 0) {
+        boolean authRequired;
+        if (constraints == null) {
+            authRequired = false;
+        } else {
+            authRequired = true;
+            for(i=0; i < constraints.length && authRequired; i++) {
+                if(!constraints[i].getAuthConstraint()) {
                     authRequired = false;
+                } else if(!constraints[i].getAllRoles()) {
+                    String [] roles = constraints[i].findAuthRoles();
+                    if(roles == null || roles.length == 0) {
+                        authRequired = false;
+                    }
                 }
             }
         }
-             
+
+        if (!authRequired) {
+            authRequired =
+                request.getCoyoteRequest().getMimeHeaders().getValue(
+                        "authorization") != null;
+        }
+
+        if (!authRequired) {
+            X509Certificate[] certs = (X509Certificate[]) request.getAttribute(
+                    Globals.CERTIFICATES_ATTR);
+            authRequired = certs != null && certs.length > 0;
+        }
+
         if(authRequired) {  
             if (log.isDebugEnabled()) {
                 log.debug(" Calling authenticate()");
@@ -530,21 +550,23 @@ public abstract class AuthenticatorBase 
             
         }
     
-        if (log.isDebugEnabled()) {
-            log.debug(" Calling accessControl()");
-        }
-        if (!realm.hasResourcePermission(request, response,
-                                         constraints,
-                                         this.context)) {
+        if (constraints != null) {
             if (log.isDebugEnabled()) {
-                log.debug(" Failed accessControl() test");
+                log.debug(" Calling accessControl()");
+            }
+            if (!realm.hasResourcePermission(request, response,
+                                             constraints,
+                                             this.context)) {
+                if (log.isDebugEnabled()) {
+                    log.debug(" Failed accessControl() test");
+                }
+                /*
+                 * ASSERT: AccessControl method has already set the
+                 * appropriate HTTP status code, so we do not have to do
+                 * anything special
+                 */
+                return;
             }
-            /*
-             * ASSERT: AccessControl method has already set the
-             * appropriate HTTP status code, so we do not have to do
-             * anything special
-             */
-            return;
         }
     
         // Any and all specified constraints have been satisfied

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1087643&r1=1087642&r2=1087643&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Fri Apr  1 10:49:43 2011
@@ -849,10 +849,24 @@ public class StandardContext extends Con
      */
     private Set<Servlet> createdServlets = new HashSet<Servlet>();
 
+    private boolean preemptiveAuthentication = false;
+
     // ----------------------------------------------------- Context Properties
 
 
     @Override
+    public boolean getPreemptiveAuthentication() {
+        return preemptiveAuthentication;
+    }
+
+
+    @Override
+    public void setPreemptiveAuthentication(boolean preemptiveAuthentication) {
+        this.preemptiveAuthentication = preemptiveAuthentication;
+    }
+
+
+    @Override
     public void setFireRequestListenersOnForwards(boolean enable) {
         fireRequestListenersOnForwards = enable;
     }

Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=1087643&r1=1087642&r2=1087643&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Fri Apr  1 10:49:43 2011
@@ -367,12 +367,17 @@ public class ContextConfig
     protected synchronized void authenticatorConfig() {
 
         LoginConfig loginConfig = context.getLoginConfig();
-        if (loginConfig == null) {
-            if (context.getIgnoreAnnotations())  {
-                return;
-            } else {
-                // Not metadata-complete, need an authenticator to support
-                // @ServletSecurity annotations
+
+        SecurityConstraint constraints[] = context.findConstraints();
+        if (context.getIgnoreAnnotations() &&
+                (constraints == null || constraints.length ==0) &&
+                !context.getPreemptiveAuthentication())  {
+            return;
+        } else {
+            if (loginConfig == null) {
+                // Not metadata-complete or security constraints present, need
+                // an authenticator to support @ServletSecurity annotations
+                // and/or constraints
                 loginConfig = DUMMY_LOGIN_CONFIG;
                 context.setLoginConfig(loginConfig);
             }

Modified: tomcat/trunk/test/org/apache/catalina/core/TestStandardWrapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/core/TestStandardWrapper.java?rev=1087643&r1=1087642&r2=1087643&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/core/TestStandardWrapper.java (original)
+++ tomcat/trunk/test/org/apache/catalina/core/TestStandardWrapper.java Fri Apr  1 10:49:43 2011
@@ -143,6 +143,30 @@ public class TestStandardWrapper extends
         assertEquals(403, rc);
     }
 
+    public void testSecurityAnnotationsNoWebXmlLoginConfig() throws Exception {
+        // Setup Tomcat instance
+        Tomcat tomcat = getTomcatInstance();
+        
+        File appDir = new File("test/webapp-3.0-servletsecurity2");
+        tomcat.addWebapp(null, "", appDir.getAbsolutePath());
+        
+        tomcat.start();
+        
+        ByteChunk bc = new ByteChunk();
+        int rc;
+        rc = getUrl("http://localhost:" + getPort() + "/protected.jsp",
+                bc, null, null);
+        
+        assertNull(bc.toString());
+        assertEquals(403, rc);
+
+        rc = getUrl("http://localhost:" + getPort() + "/unprotected.jsp",
+                bc, null, null);
+        
+        assertEquals(200, rc);
+        assertTrue(bc.toString().contains("00-OK"));
+    }
+
     private void doTestSecurityAnnotationsAddServlet(boolean useCreateServlet)
             throws Exception {
 

Added: tomcat/trunk/test/webapp-3.0-servletsecurity2/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/webapp-3.0-servletsecurity2/WEB-INF/web.xml?rev=1087643&view=auto
==============================================================================
--- tomcat/trunk/test/webapp-3.0-servletsecurity2/WEB-INF/web.xml (added)
+++ tomcat/trunk/test/webapp-3.0-servletsecurity2/WEB-INF/web.xml Fri Apr  1 10:49:43 2011
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  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.
+-->
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
+                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+  version="3.0"
+  metadata-complete="true">  
+
+  <!--
+    WARNING:
+    For the unit tests to work correctly, no login-config may be configured in
+    the web.xml.
+  -->
+
+  <display-name>Tomcat Test Application</display-name>
+  <description>
+     Used as part of the Tomcat unit tests when a full web application is
+     required.
+  </description>
+  
+  <security-constraint>
+    <auth-constraint/>
+    <web-resource-collection>
+      <url-pattern>/protected.jsp</url-pattern>
+    </web-resource-collection>
+  </security-constraint>
+</web-app>
\ No newline at end of file

Propchange: tomcat/trunk/test/webapp-3.0-servletsecurity2/WEB-INF/web.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/test/webapp-3.0-servletsecurity2/protected.jsp
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/webapp-3.0-servletsecurity2/protected.jsp?rev=1087643&view=auto
==============================================================================
--- tomcat/trunk/test/webapp-3.0-servletsecurity2/protected.jsp (added)
+++ tomcat/trunk/test/webapp-3.0-servletsecurity2/protected.jsp Fri Apr  1 10:49:43 2011
@@ -0,0 +1,23 @@
+<%--
+ 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.
+--%>
+<html>
+  <head><title>Protected page</title></head>
+  <body>
+    <p>00-OK</p>
+  </body>
+</html>
+

Propchange: tomcat/trunk/test/webapp-3.0-servletsecurity2/protected.jsp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/test/webapp-3.0-servletsecurity2/unprotected.jsp
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/webapp-3.0-servletsecurity2/unprotected.jsp?rev=1087643&view=auto
==============================================================================
--- tomcat/trunk/test/webapp-3.0-servletsecurity2/unprotected.jsp (added)
+++ tomcat/trunk/test/webapp-3.0-servletsecurity2/unprotected.jsp Fri Apr  1 10:49:43 2011
@@ -0,0 +1,23 @@
+<%--
+ 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.
+--%>
+<html>
+  <head><title>Unprotected page</title></head>
+  <body>
+    <p>00-OK</p>
+  </body>
+</html>
+

Propchange: tomcat/trunk/test/webapp-3.0-servletsecurity2/unprotected.jsp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1087643&r1=1087642&r2=1087643&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Fri Apr  1 10:49:43 2011
@@ -73,6 +73,11 @@
         When using parallel deployment, correctly handle the scenario when the
         client sends multiple JSESSIONID cookies. (markt)
       </fix>
+      <add>
+        <bug>12428</bug>: Add support (disabled by default) for preemptive
+        authentication. This can be configured per context. Based on a patch
+        suggested by Werner Donn. (markt)
+      </add>
       <fix>
         <bug>50929</bug>: When wrapping an exception, include the root cause.
         Patch provided by sebb. (markt) 

Modified: tomcat/trunk/webapps/docs/config/context.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=1087643&r1=1087642&r2=1087643&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/context.xml (original)
+++ tomcat/trunk/webapps/docs/config/context.xml Fri Apr  1 10:49:43 2011
@@ -312,6 +312,16 @@
         filenames used for either the .xml context file or the docBase.</p>
       </attribute>
 
+      <attribute name="preemptiveAuthentication" required="false">
+        <p>When set to <code>true</code> and the user presents credentials for a
+        resource that is not protected by a security constraint, if the
+        authenticator supports preemptive authentication (the standard
+        authenticators provided with Tomcat do) then the user&apos; credentials
+        will be processed. If not specified, the default of <code>false</code>is
+        used.
+        </p>
+      </attribute>
+
       <attribute name="privileged" required="false">
         <p>Set to <code>true</code> to allow this context to use container
         servlets, like the manager servlet. Use of the <code>privileged</code>



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