Blame SOURCES/tomcat-7.0.76-CVE-2018-1305.patch

9a9096
commit 2aac69f694d42d9219eb27018b3da0ae1bdd73ab
9a9096
Author: Mark Thomas <markt@apache.org>
9a9096
Date:   Tue Feb 6 12:49:49 2018 +0000
9a9096
9a9096
    Process all ServletSecurity annotations at web application start rather
9a9096
    than at servlet load time to ensure constraints are applied
9a9096
    consistently.
9a9096
    
9a9096
    git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk@1823322 13f79535-47bb-0310-9956-ffa450edef68
9a9096
9a9096
diff -up java/org/apache/catalina/authenticator/AuthenticatorBase.java.orig java/org/apache/catalina/authenticator/AuthenticatorBase.java
9a9096
--- java/org/apache/catalina/authenticator/AuthenticatorBase.java.orig	2019-02-28 15:41:52.561346049 -0500
9a9096
+++ java/org/apache/catalina/authenticator/AuthenticatorBase.java	2019-02-28 15:44:09.129930251 -0500
9a9096
@@ -40,7 +40,6 @@ import org.apache.catalina.Manager;
9a9096
 import org.apache.catalina.Realm;
9a9096
 import org.apache.catalina.Session;
9a9096
 import org.apache.catalina.Valve;
9a9096
-import org.apache.catalina.Wrapper;
9a9096
 import org.apache.catalina.connector.Request;
9a9096
 import org.apache.catalina.connector.Response;
9a9096
 import org.apache.catalina.deploy.LoginConfig;
9a9096
@@ -488,13 +487,6 @@ public abstract class AuthenticatorBase
9a9096
             }
9a9096
         }
9a9096
 
9a9096
-        // The Servlet may specify security constraints through annotations.
9a9096
-        // Ensure that they have been processed before constraints are checked
9a9096
-        Wrapper wrapper = (Wrapper) request.getMappingData().wrapper;
9a9096
-        if (wrapper != null) {
9a9096
-            wrapper.servletSecurityAnnotationScan();
9a9096
-        }
9a9096
-
9a9096
         Realm realm = this.context.getRealm();
9a9096
         // Is this request URI subject to a security constraint?
9a9096
         SecurityConstraint [] constraints
9a9096
diff -up java/org/apache/catalina/core/ApplicationContext.java.orig java/org/apache/catalina/core/ApplicationContext.java
9a9096
--- java/org/apache/catalina/core/ApplicationContext.java.orig	2017-03-09 08:51:39.000000000 -0500
9a9096
+++ java/org/apache/catalina/core/ApplicationContext.java	2019-02-28 15:44:09.130930248 -0500
9a9096
@@ -53,8 +53,10 @@ import javax.servlet.ServletException;
9a9096
 import javax.servlet.ServletRegistration;
9a9096
 import javax.servlet.ServletRequestAttributeListener;
9a9096
 import javax.servlet.ServletRequestListener;
9a9096
+import javax.servlet.ServletSecurityElement;
9a9096
 import javax.servlet.SessionCookieConfig;
9a9096
 import javax.servlet.SessionTrackingMode;
9a9096
+import javax.servlet.annotation.ServletSecurity;
9a9096
 import javax.servlet.descriptor.JspConfigDescriptor;
9a9096
 import javax.servlet.http.HttpSessionAttributeListener;
9a9096
 import javax.servlet.http.HttpSessionListener;
9a9096
@@ -69,6 +71,7 @@ import org.apache.catalina.Wrapper;
9a9096
 import org.apache.catalina.connector.Connector;
9a9096
 import org.apache.catalina.deploy.FilterDef;
9a9096
 import org.apache.catalina.util.ResourceSet;
9a9096
+import org.apache.catalina.util.Introspection;
9a9096
 import org.apache.catalina.util.ServerInfo;
9a9096
 import org.apache.catalina.util.URLEncoder;
9a9096
 import org.apache.naming.resources.DirContextURLStreamHandler;
9a9096
@@ -1186,14 +1189,27 @@ public class ApplicationContext implemen
9a9096
             }
9a9096
         }
9a9096
 
9a9096
+        ServletSecurity annotation = null;
9a9096
         if (servlet == null) {
9a9096
             wrapper.setServletClass(servletClass);
9a9096
+            Class clazz = Introspection.loadClass(context, servletClass);
9a9096
+            if (clazz != null) {
9a9096
+                annotation = clazz.getAnnotation(ServletSecurity.class);
9a9096
+            }
9a9096
         } else {
9a9096
             wrapper.setServletClass(servlet.getClass().getName());
9a9096
             wrapper.setServlet(servlet);
9a9096
+            if (context.wasCreatedDynamicServlet(servlet)) {
9a9096
+                annotation = servlet.getClass().getAnnotation(ServletSecurity.class);
9a9096
+            }
9a9096
         }
9a9096
 
9a9096
-        return context.dynamicServletAdded(wrapper);
9a9096
+        ServletRegistration.Dynamic registration =
9a9096
+                new ApplicationServletRegistration(wrapper, context);
9a9096
+        if (annotation != null) {
9a9096
+            registration.setServletSecurity(new ServletSecurityElement(annotation));
9a9096
+        }
9a9096
+        return registration;
9a9096
     }
9a9096
 
9a9096
 
9a9096
diff -up java/org/apache/catalina/core/ApplicationServletRegistration.java.orig java/org/apache/catalina/core/ApplicationServletRegistration.java
9a9096
--- java/org/apache/catalina/core/ApplicationServletRegistration.java.orig	2019-02-28 15:41:52.568346028 -0500
9a9096
+++ java/org/apache/catalina/core/ApplicationServletRegistration.java	2019-02-28 15:44:09.130930248 -0500
9a9096
@@ -5,9 +5,9 @@
9a9096
  * The ASF licenses this file to You under the Apache License, Version 2.0
9a9096
  * (the "License"); you may not use this file except in compliance with
9a9096
  * the License.  You may obtain a copy of the License at
9a9096
- * 
9a9096
+ *
9a9096
  *      http://www.apache.org/licenses/LICENSE-2.0
9a9096
- * 
9a9096
+ *
9a9096
  * Unless required by applicable law or agreed to in writing, software
9a9096
  * distributed under the License is distributed on an "AS IS" BASIS,
9a9096
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9a9096
@@ -41,15 +41,16 @@ public class ApplicationServletRegistrat
9a9096
      */
9a9096
     private static final StringManager sm =
9a9096
       StringManager.getManager(Constants.Package);
9a9096
-    
9a9096
-    private Wrapper wrapper;
9a9096
-    private Context context;
9a9096
-    
9a9096
+
9a9096
+    private final Wrapper wrapper;
9a9096
+    private final Context context;
9a9096
+    private ServletSecurityElement constraint;
9a9096
+
9a9096
     public ApplicationServletRegistration(Wrapper wrapper,
9a9096
             Context context) {
9a9096
         this.wrapper = wrapper;
9a9096
         this.context = context;
9a9096
-        
9a9096
+
9a9096
     }
9a9096
 
9a9096
     @Override
9a9096
@@ -65,9 +66,9 @@ public class ApplicationServletRegistrat
9a9096
     @Override
9a9096
     public Map<String, String> getInitParameters() {
9a9096
         ParameterMap<String,String> result = new ParameterMap<String,String>();
9a9096
-        
9a9096
+
9a9096
         String[] parameterNames = wrapper.findInitParameters();
9a9096
-        
9a9096
+
9a9096
         for (String parameterName : parameterNames) {
9a9096
             result.put(parameterName, wrapper.findInitParameter(parameterName));
9a9096
         }
9a9096
@@ -91,7 +92,7 @@ public class ApplicationServletRegistrat
9a9096
         if (getInitParameter(name) != null) {
9a9096
             return false;
9a9096
         }
9a9096
-        
9a9096
+
9a9096
         wrapper.addInitParameter(name, value);
9a9096
 
9a9096
         return true;
9a9096
@@ -99,9 +100,9 @@ public class ApplicationServletRegistrat
9a9096
 
9a9096
     @Override
9a9096
     public Set<String> setInitParameters(Map<String, String> initParameters) {
9a9096
-        
9a9096
+
9a9096
         Set<String> conflicts = new HashSet<String>();
9a9096
-        
9a9096
+
9a9096
         for (Map.Entry<String, String> entry : initParameters.entrySet()) {
9a9096
             if (entry.getKey() == null || entry.getValue() == null) {
9a9096
                 throw new IllegalArgumentException(sm.getString(
9a9096
@@ -151,13 +152,14 @@ public class ApplicationServletRegistrat
9a9096
                     "applicationServletRegistration.setServletSecurity.iae",
9a9096
                     getName(), context.getName()));
9a9096
         }
9a9096
-        
9a9096
+
9a9096
         if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
9a9096
             throw new IllegalStateException(sm.getString(
9a9096
                     "applicationServletRegistration.setServletSecurity.ise",
9a9096
                     getName(), context.getName()));
9a9096
         }
9a9096
 
9a9096
+        this.constraint = constraint;
9a9096
         return context.addServletSecurity(this, constraint);
9a9096
     }
9a9096
 
9a9096
@@ -167,9 +169,9 @@ public class ApplicationServletRegistrat
9a9096
         if (urlPatterns == null) {
9a9096
             return Collections.emptySet();
9a9096
         }
9a9096
-        
9a9096
+
9a9096
         Set<String> conflicts = new HashSet<String>();
9a9096
-        
9a9096
+
9a9096
         for (String urlPattern : urlPatterns) {
9a9096
             String wrapperName = context.findServletMapping(urlPattern);
9a9096
             if (wrapperName != null) {
9a9096
@@ -187,10 +189,15 @@ public class ApplicationServletRegistrat
9a9096
         if (!conflicts.isEmpty()) {
9a9096
             return conflicts;
9a9096
         }
9a9096
-        
9a9096
+
9a9096
         for (String urlPattern : urlPatterns) {
9a9096
             context.addServletMapping(urlPattern, wrapper.getName());
9a9096
         }
9a9096
+
9a9096
+        if (constraint != null) {
9a9096
+            context.addServletSecurity(this, constraint);
9a9096
+        }
9a9096
+
9a9096
         return Collections.emptySet();
9a9096
     }
9a9096
 
9a9096
@@ -199,7 +206,7 @@ public class ApplicationServletRegistrat
9a9096
 
9a9096
         Set<String> result = new HashSet<String>();
9a9096
         String servletName = wrapper.getName();
9a9096
-        
9a9096
+
9a9096
         String[] urlPatterns = context.findServletMappings();
9a9096
         for (String urlPattern : urlPatterns) {
9a9096
             String name = context.findServletMapping(urlPattern);
9a9096
@@ -214,5 +221,5 @@ public class ApplicationServletRegistrat
9a9096
     public String getRunAsRole() {
9a9096
         return wrapper.getRunAs();
9a9096
     }
9a9096
-    
9a9096
+
9a9096
 }
9a9096
diff -up java/org/apache/catalina/core/StandardContext.java.orig java/org/apache/catalina/core/StandardContext.java
9a9096
--- java/org/apache/catalina/core/StandardContext.java.orig	2017-03-09 08:51:39.000000000 -0500
9a9096
+++ java/org/apache/catalina/core/StandardContext.java	2019-02-28 15:44:09.132930242 -0500
9a9096
@@ -4813,27 +4813,36 @@ public class StandardContext extends Con
9a9096
     }
9a9096
 
9a9096
     /**
9a9096
-     * hook to register that we need to scan for security annotations.
9a9096
-     * @param wrapper   The wrapper for the Servlet that was added
9a9096
+     * Create a servlet registration.
9a9096
+     *
9a9096
+     * @param wrapper The wrapper for which the registration should be created.
9a9096
+     *
9a9096
+     * @return An appropriate registration
9a9096
+     *
9a9096
+     * @deprecated This will be removed in Tomcat 9. The registration should be
9a9096
+     *             created directly.
9a9096
      */
9a9096
+    @Deprecated
9a9096
     public ServletRegistration.Dynamic dynamicServletAdded(Wrapper wrapper) {
9a9096
-        Servlet s = wrapper.getServlet();
9a9096
-        if (s != null && createdServlets.contains(s)) {
9a9096
-            // Mark the wrapper to indicate annotations need to be scanned
9a9096
-            wrapper.setServletSecurityAnnotationScanRequired(true);
9a9096
-        }
9a9096
         return new ApplicationServletRegistration(wrapper, this);
9a9096
     }
9a9096
 
9a9096
     /**
9a9096
-     * hook to track which registrations need annotation scanning
9a9096
-     * @param servlet
9a9096
+     * Hook to track which Servlets were created via
9a9096
+     * {@link ServletContext#createServlet(Class)}.
9a9096
+     *
9a9096
+     * @param servlet the created Servlet
9a9096
      */
9a9096
     public void dynamicServletCreated(Servlet servlet) {
9a9096
         createdServlets.add(servlet);
9a9096
     }
9a9096
 
9a9096
 
9a9096
+    public boolean wasCreatedDynamicServlet(Servlet servlet) {
9a9096
+        return createdServlets.contains(servlet);
9a9096
+    }
9a9096
+
9a9096
+
9a9096
     /**
9a9096
      * A helper class to manage the filter mappings in a Context.
9a9096
      */
9a9096
diff -up java/org/apache/catalina/core/StandardWrapper.java.orig java/org/apache/catalina/core/StandardWrapper.java
9a9096
--- java/org/apache/catalina/core/StandardWrapper.java.orig	2019-02-28 15:41:52.576346004 -0500
9a9096
+++ java/org/apache/catalina/core/StandardWrapper.java	2019-02-28 15:44:09.133930239 -0500
9a9096
@@ -5,17 +5,15 @@
9a9096
  * The ASF licenses this file to You under the Apache License, Version 2.0
9a9096
  * (the "License"); you may not use this file except in compliance with
9a9096
  * the License.  You may obtain a copy of the License at
9a9096
- * 
9a9096
+ *
9a9096
  *      http://www.apache.org/licenses/LICENSE-2.0
9a9096
- * 
9a9096
+ *
9a9096
  * Unless required by applicable law or agreed to in writing, software
9a9096
  * distributed under the License is distributed on an "AS IS" BASIS,
9a9096
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9a9096
  * See the License for the specific language governing permissions and
9a9096
  * limitations under the License.
9a9096
  */
9a9096
-
9a9096
-
9a9096
 package org.apache.catalina.core;
9a9096
 
9a9096
 import java.io.PrintStream;
9a9096
@@ -44,11 +42,9 @@ import javax.servlet.ServletContext;
9a9096
 import javax.servlet.ServletException;
9a9096
 import javax.servlet.ServletRequest;
9a9096
 import javax.servlet.ServletResponse;
9a9096
-import javax.servlet.ServletSecurityElement;
9a9096
 import javax.servlet.SingleThreadModel;
9a9096
 import javax.servlet.UnavailableException;
9a9096
 import javax.servlet.annotation.MultipartConfig;
9a9096
-import javax.servlet.annotation.ServletSecurity;
9a9096
 
9a9096
 import org.apache.catalina.Container;
9a9096
 import org.apache.catalina.ContainerServlet;
9a9096
@@ -114,12 +110,12 @@ public class StandardWrapper extends Con
9a9096
      * servlet is considered permanent.
9a9096
      */
9a9096
     protected long available = 0L;
9a9096
-    
9a9096
+
9a9096
     /**
9a9096
-     * The broadcaster that sends j2ee notifications. 
9a9096
+     * The broadcaster that sends j2ee notifications.
9a9096
      */
9a9096
     protected NotificationBroadcasterSupport broadcaster = null;
9a9096
-    
9a9096
+
9a9096
     /**
9a9096
      * The count of allocations that are currently active (even if they
9a9096
      * are for the same instance, as will be true on a non-STM servlet).
9a9096
@@ -231,12 +227,12 @@ public class StandardWrapper extends Con
9a9096
      */
9a9096
     protected Stack<Servlet> instancePool = null;
9a9096
 
9a9096
-    
9a9096
+
9a9096
     /**
9a9096
      * Wait time for servlet unload in ms.
9a9096
      */
9a9096
     protected long unloadDelay = 2000;
9a9096
-    
9a9096
+
9a9096
 
9a9096
     /**
9a9096
      * True if this StandardWrapper is for the JspServlet
9a9096
@@ -259,12 +255,12 @@ public class StandardWrapper extends Con
9a9096
     protected StandardWrapperValve swValve;
9a9096
     protected long loadTime=0;
9a9096
     protected int classLoadTime=0;
9a9096
-    
9a9096
+
9a9096
     /**
9a9096
      * Multipart config
9a9096
      */
9a9096
     protected MultipartConfigElement multipartConfigElement = null;
9a9096
-    
9a9096
+
9a9096
     /**
9a9096
      * Async support
9a9096
      */
9a9096
@@ -275,26 +271,24 @@ public class StandardWrapper extends Con
9a9096
      */
9a9096
     protected boolean enabled = true;
9a9096
 
9a9096
-    protected volatile boolean servletSecurityAnnotationScanRequired = false;
9a9096
-
9a9096
     private boolean overridable = false;
9a9096
-    
9a9096
+
9a9096
     /**
9a9096
-     * Static class array used when the SecurityManager is turned on and 
9a9096
+     * Static class array used when the SecurityManager is turned on and
9a9096
      * Servlet.init is invoked.
9a9096
      */
9a9096
     protected static Class[] classType = new Class[]{ServletConfig.class};
9a9096
-    
9a9096
-    
9a9096
+
9a9096
+
9a9096
     /**
9a9096
-     * Static class array used when the SecurityManager is turned on and 
9a9096
+     * Static class array used when the SecurityManager is turned on and
9a9096
      * Servlet.service  is invoked.
9a9096
-     */                                                 
9a9096
+     */
9a9096
     @Deprecated
9a9096
     protected static Class[] classTypeUsedInService = new Class[]{
9a9096
                                                          ServletRequest.class,
9a9096
                                                          ServletResponse.class};
9a9096
-    
9a9096
+
9a9096
 
9a9096
     private final ReentrantReadWriteLock parametersLock =
9a9096
             new ReentrantReadWriteLock();
9a9096
@@ -625,7 +619,7 @@ public class StandardWrapper extends Con
9a9096
     public String[] getServletMethods() throws ServletException {
9a9096
 
9a9096
         instance = loadServlet();
9a9096
-        
9a9096
+
9a9096
         Class servletClazz = instance.getClass();
9a9096
         if (!javax.servlet.http.HttpServlet.class.isAssignableFrom(
9a9096
                                                         servletClazz)) {
9a9096
@@ -665,8 +659,8 @@ public class StandardWrapper extends Con
9a9096
     public Servlet getServlet() {
9a9096
         return instance;
9a9096
     }
9a9096
-    
9a9096
-    
9a9096
+
9a9096
+
9a9096
     /**
9a9096
      * Set the associated servlet instance.
9a9096
      */
9a9096
@@ -675,13 +669,13 @@ public class StandardWrapper extends Con
9a9096
         instance = servlet;
9a9096
     }
9a9096
 
9a9096
-    
9a9096
+
9a9096
     /**
9a9096
      * {@inheritDoc}
9a9096
      */
9a9096
     @Override
9a9096
     public void setServletSecurityAnnotationScanRequired(boolean b) {
9a9096
-        this.servletSecurityAnnotationScanRequired = b;
9a9096
+        // NO-OP
9a9096
     }
9a9096
 
9a9096
     // --------------------------------------------------------- Public Methods
9a9096
@@ -695,19 +689,19 @@ public class StandardWrapper extends Con
9a9096
     @Override
9a9096
     public void backgroundProcess() {
9a9096
         super.backgroundProcess();
9a9096
-        
9a9096
+
9a9096
         if (!getState().isAvailable())
9a9096
             return;
9a9096
-        
9a9096
+
9a9096
         if (getServlet() != null && (getServlet() instanceof PeriodicEventListener)) {
9a9096
             ((PeriodicEventListener) getServlet()).periodicEvent();
9a9096
         }
9a9096
     }
9a9096
-    
9a9096
-    
9a9096
+
9a9096
+
9a9096
     /**
9a9096
      * Extract the root cause from a servlet exception.
9a9096
-     * 
9a9096
+     *
9a9096
      * @param e The servlet exception
9a9096
      */
9a9096
     public static Throwable getRootCause(ServletException e) {
9a9096
@@ -836,7 +830,7 @@ public class StandardWrapper extends Con
9a9096
         }
9a9096
 
9a9096
         boolean newInstance = false;
9a9096
-        
9a9096
+
9a9096
         // If not SingleThreadedModel, return the same instance every time
9a9096
         if (!singleThreadModel) {
9a9096
             // Load and initialize our instance if necessary
9a9096
@@ -1070,7 +1064,7 @@ public class StandardWrapper extends Con
9a9096
     @Override
9a9096
     public synchronized void load() throws ServletException {
9a9096
         instance = loadServlet();
9a9096
-        
9a9096
+
9a9096
         if (!instanceInitialized) {
9a9096
             initServlet(instance);
9a9096
         }
9a9096
@@ -1078,12 +1072,12 @@ public class StandardWrapper extends Con
9a9096
         if (isJspServlet) {
9a9096
             StringBuilder oname =
9a9096
                 new StringBuilder(MBeanUtils.getDomain(getParent()));
9a9096
-            
9a9096
+
9a9096
             oname.append(":type=JspMonitor,name=");
9a9096
             oname.append(getName());
9a9096
-            
9a9096
+
9a9096
             oname.append(getWebModuleKeyProperties());
9a9096
-            
9a9096
+
9a9096
             try {
9a9096
                 jspMonitorON = new ObjectName(oname.toString());
9a9096
                 Registry.getRegistry(null, null)
9a9096
@@ -1161,8 +1155,6 @@ public class StandardWrapper extends Con
9a9096
                 }
9a9096
             }
9a9096
 
9a9096
-            processServletSecurityAnnotation(servlet.getClass());
9a9096
-
9a9096
             // Special handling for ContainerServlet instances
9a9096
             if ((servlet instanceof ContainerServlet) &&
9a9096
                     (isContainerProvidedServlet(servletClass) ||
9a9096
@@ -1205,44 +1197,13 @@ public class StandardWrapper extends Con
9a9096
      */
9a9096
     @Override
9a9096
     public void servletSecurityAnnotationScan() throws ServletException {
9a9096
-        if (getServlet() == null) {
9a9096
-            Class clazz = null;
9a9096
-            try {
9a9096
-                clazz = getParent().getLoader().getClassLoader().loadClass(
9a9096
-                        getServletClass());
9a9096
-                processServletSecurityAnnotation(clazz);
9a9096
-            } catch (ClassNotFoundException e) {
9a9096
-                // Safe to ignore. No class means no annotations to process
9a9096
-            }
9a9096
-        } else {
9a9096
-            if (servletSecurityAnnotationScanRequired) {
9a9096
-                processServletSecurityAnnotation(getServlet().getClass());
9a9096
-            }
9a9096
-        }
9a9096
+        // NO-OP
9a9096
     }
9a9096
 
9a9096
-    private void processServletSecurityAnnotation(Class clazz) {
9a9096
-        // Calling this twice isn't harmful so no syncs
9a9096
-        servletSecurityAnnotationScanRequired = false;
9a9096
-
9a9096
-        Context ctxt = (Context) getParent();
9a9096
-        
9a9096
-        if (ctxt.getIgnoreAnnotations()) {
9a9096
-            return;
9a9096
-        }
9a9096
-
9a9096
-        ServletSecurity secAnnotation =
9a9096
-            clazz.getAnnotation(ServletSecurity.class);
9a9096
-        if (secAnnotation != null) {
9a9096
-            ctxt.addServletSecurity(
9a9096
-                    new ApplicationServletRegistration(this, ctxt),
9a9096
-                    new ServletSecurityElement(secAnnotation));
9a9096
-        }
9a9096
-    }
9a9096
 
9a9096
     private synchronized void initServlet(Servlet servlet)
9a9096
             throws ServletException {
9a9096
-        
9a9096
+
9a9096
         if (instanceInitialized && !singleThreadModel) return;
9a9096
 
9a9096
         // Call the initialization method of this servlet
9a9096
@@ -1454,12 +1415,12 @@ public class StandardWrapper extends Con
9a9096
             if (swallowOutput) {
9a9096
                 SystemLogHandler.startCapture();
9a9096
             }
9a9096
-    
9a9096
+
9a9096
             // Call the servlet destroy() method
9a9096
             try {
9a9096
                 instanceSupport.fireInstanceEvent
9a9096
                   (InstanceEvent.BEFORE_DESTROY_EVENT, instance);
9a9096
-    
9a9096
+
9a9096
                 if( Globals.IS_SECURITY_ENABLED) {
9a9096
                     try {
9a9096
                         SecurityUtil.doAsPrivilege("destroy",
9a9096
@@ -1470,7 +1431,7 @@ public class StandardWrapper extends Con
9a9096
                 } else {
9a9096
                     instance.destroy();
9a9096
                 }
9a9096
-                
9a9096
+
9a9096
                 instanceSupport.fireInstanceEvent
9a9096
                   (InstanceEvent.AFTER_DESTROY_EVENT, instance);
9a9096
 
9a9096
@@ -1701,7 +1662,7 @@ public class StandardWrapper extends Con
9a9096
     public boolean isAsyncSupported() {
9a9096
         return asyncSupported;
9a9096
     }
9a9096
-    
9a9096
+
9a9096
     @Override
9a9096
     public void setAsyncSupported(boolean asyncSupported) {
9a9096
         this.asyncSupported = asyncSupported;
9a9096
@@ -1711,7 +1672,7 @@ public class StandardWrapper extends Con
9a9096
     public boolean isEnabled() {
9a9096
         return enabled;
9a9096
     }
9a9096
-    
9a9096
+
9a9096
     @Override
9a9096
     public void setEnabled(boolean enabled) {
9a9096
         this.enabled = enabled;
9a9096
@@ -1787,24 +1748,24 @@ public class StandardWrapper extends Con
9a9096
      */
9a9096
     @Override
9a9096
     protected synchronized void startInternal() throws LifecycleException {
9a9096
-    
9a9096
-        // Send j2ee.state.starting notification 
9a9096
+
9a9096
+        // Send j2ee.state.starting notification
9a9096
         if (this.getObjectName() != null) {
9a9096
-            Notification notification = new Notification("j2ee.state.starting", 
9a9096
-                                                        this.getObjectName(), 
9a9096
+            Notification notification = new Notification("j2ee.state.starting",
9a9096
+                                                        this.getObjectName(),
9a9096
                                                         sequenceNumber++);
9a9096
             broadcaster.sendNotification(notification);
9a9096
         }
9a9096
-        
9a9096
+
9a9096
         // Start up this component
9a9096
         super.startInternal();
9a9096
 
9a9096
         setAvailable(0L);
9a9096
 
9a9096
-        // Send j2ee.state.running notification 
9a9096
+        // Send j2ee.state.running notification
9a9096
         if (this.getObjectName() != null) {
9a9096
-            Notification notification = 
9a9096
-                new Notification("j2ee.state.running", this.getObjectName(), 
9a9096
+            Notification notification =
9a9096
+                new Notification("j2ee.state.running", this.getObjectName(),
9a9096
                                 sequenceNumber++);
9a9096
             broadcaster.sendNotification(notification);
9a9096
         }
9a9096
@@ -1823,15 +1784,15 @@ public class StandardWrapper extends Con
9a9096
     protected synchronized void stopInternal() throws LifecycleException {
9a9096
 
9a9096
         setAvailable(Long.MAX_VALUE);
9a9096
-        
9a9096
-        // Send j2ee.state.stopping notification 
9a9096
+
9a9096
+        // Send j2ee.state.stopping notification
9a9096
         if (this.getObjectName() != null) {
9a9096
-            Notification notification = 
9a9096
-                new Notification("j2ee.state.stopping", this.getObjectName(), 
9a9096
+            Notification notification =
9a9096
+                new Notification("j2ee.state.stopping", this.getObjectName(),
9a9096
                                 sequenceNumber++);
9a9096
             broadcaster.sendNotification(notification);
9a9096
         }
9a9096
-        
9a9096
+
9a9096
         // Shut down our servlet instance (if it has been initialized)
9a9096
         try {
9a9096
             unload();
9a9096
@@ -1843,43 +1804,43 @@ public class StandardWrapper extends Con
9a9096
         // Shut down this component
9a9096
         super.stopInternal();
9a9096
 
9a9096
-        // Send j2ee.state.stopped notification 
9a9096
+        // Send j2ee.state.stopped notification
9a9096
         if (this.getObjectName() != null) {
9a9096
-            Notification notification = 
9a9096
-                new Notification("j2ee.state.stopped", this.getObjectName(), 
9a9096
+            Notification notification =
9a9096
+                new Notification("j2ee.state.stopped", this.getObjectName(),
9a9096
                                 sequenceNumber++);
9a9096
             broadcaster.sendNotification(notification);
9a9096
         }
9a9096
-        
9a9096
-        // Send j2ee.object.deleted notification 
9a9096
-        Notification notification = 
9a9096
-            new Notification("j2ee.object.deleted", this.getObjectName(), 
9a9096
+
9a9096
+        // Send j2ee.object.deleted notification
9a9096
+        Notification notification =
9a9096
+            new Notification("j2ee.object.deleted", this.getObjectName(),
9a9096
                             sequenceNumber++);
9a9096
         broadcaster.sendNotification(notification);
9a9096
 
9a9096
     }
9a9096
 
9a9096
-    
9a9096
+
9a9096
     @Override
9a9096
     protected String getObjectNameKeyProperties() {
9a9096
 
9a9096
         StringBuilder keyProperties =
9a9096
             new StringBuilder("j2eeType=Servlet,name=");
9a9096
-        
9a9096
+
9a9096
         String name = getName();
9a9096
         if (Util.objectNameValueNeedsQuote(name)) {
9a9096
             name = ObjectName.quote(name);
9a9096
         }
9a9096
         keyProperties.append(name);
9a9096
-        
9a9096
+
9a9096
         keyProperties.append(getWebModuleKeyProperties());
9a9096
 
9a9096
         return keyProperties.toString();
9a9096
     }
9a9096
-        
9a9096
+
9a9096
 
9a9096
     private String getWebModuleKeyProperties() {
9a9096
-        
9a9096
+
9a9096
         StringBuilder keyProperties = new StringBuilder(",WebModule=//");
9a9096
         String hostName = getParent().getParent().getName();
9a9096
         if (hostName == null) {
9a9096
@@ -1887,7 +1848,7 @@ public class StandardWrapper extends Con
9a9096
         } else {
9a9096
             keyProperties.append(hostName);
9a9096
         }
9a9096
-        
9a9096
+
9a9096
         String contextName = ((Context) getParent()).getName();
9a9096
         if (!contextName.startsWith("/")) {
9a9096
             keyProperties.append('/');
9a9096
@@ -1898,7 +1859,7 @@ public class StandardWrapper extends Con
9a9096
         if (parent instanceof StandardContext) {
9a9096
             ctx = (StandardContext) getParent();
9a9096
         }
9a9096
-        
9a9096
+
9a9096
         keyProperties.append(",J2EEApplication=");
9a9096
         if (ctx == null) {
9a9096
             keyProperties.append("none");
9a9096
@@ -1911,10 +1872,10 @@ public class StandardWrapper extends Con
9a9096
         } else {
9a9096
             keyProperties.append(ctx.getJ2EEServer());
9a9096
         }
9a9096
-        
9a9096
+
9a9096
         return keyProperties.toString();
9a9096
     }
9a9096
-    
9a9096
+
9a9096
 
9a9096
     /**
9a9096
      * JSR 77. Always return false.
9a9096
@@ -1922,19 +1883,19 @@ public class StandardWrapper extends Con
9a9096
     public boolean isStateManageable() {
9a9096
         return false;
9a9096
     }
9a9096
-    
9a9096
 
9a9096
-    /* Remove a JMX notificationListener 
9a9096
+
9a9096
+    /* Remove a JMX notificationListener
9a9096
      * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
9a9096
      */
9a9096
     @Override
9a9096
-    public void removeNotificationListener(NotificationListener listener, 
9a9096
+    public void removeNotificationListener(NotificationListener listener,
9a9096
             NotificationFilter filter, Object object) throws ListenerNotFoundException {
9a9096
         broadcaster.removeNotificationListener(listener,filter,object);
9a9096
     }
9a9096
-    
9a9096
+
9a9096
     protected MBeanNotificationInfo[] notificationInfo;
9a9096
-    
9a9096
+
9a9096
     /* Get JMX Broadcaster Info
9a9096
      * @TODO use StringManager for international support!
9a9096
      * @TODO This two events we not send j2ee.state.failed and j2ee.attribute.changed!
9a9096
@@ -1949,7 +1910,7 @@ public class StandardWrapper extends Con
9a9096
                     "j2ee.object.created"},
9a9096
                     Notification.class.getName(),
9a9096
                     "servlet is created"
9a9096
-                    ), 
9a9096
+                    ),
9a9096
                     new MBeanNotificationInfo(new String[] {
9a9096
                     "j2ee.state.starting"},
9a9096
                     Notification.class.getName(),
9a9096
@@ -1980,37 +1941,37 @@ public class StandardWrapper extends Con
9a9096
 
9a9096
         return notificationInfo;
9a9096
     }
9a9096
-    
9a9096
-    
9a9096
+
9a9096
+
9a9096
     /* Add a JMX-NotificationListener
9a9096
      * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
9a9096
      */
9a9096
     @Override
9a9096
-    public void addNotificationListener(NotificationListener listener, 
9a9096
+    public void addNotificationListener(NotificationListener listener,
9a9096
             NotificationFilter filter, Object object) throws IllegalArgumentException {
9a9096
         broadcaster.addNotificationListener(listener,filter,object);
9a9096
     }
9a9096
-    
9a9096
-    
9a9096
+
9a9096
+
9a9096
     /**
9a9096
-     * Remove a JMX-NotificationListener 
9a9096
+     * Remove a JMX-NotificationListener
9a9096
      * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
9a9096
      */
9a9096
     @Override
9a9096
-    public void removeNotificationListener(NotificationListener listener) 
9a9096
+    public void removeNotificationListener(NotificationListener listener)
9a9096
         throws ListenerNotFoundException {
9a9096
         broadcaster.removeNotificationListener(listener);
9a9096
     }
9a9096
-    
9a9096
-    
9a9096
+
9a9096
+
9a9096
      // ------------------------------------------------------------- Attributes
9a9096
-        
9a9096
-        
9a9096
+
9a9096
+
9a9096
     @Deprecated
9a9096
     public boolean isEventProvider() {
9a9096
         return false;
9a9096
     }
9a9096
-    
9a9096
+
9a9096
     @Deprecated
9a9096
     public boolean isStatisticsProvider() {
9a9096
         return false;
9a9096
diff -up java/org/apache/catalina/startup/ContextConfig.java.orig java/org/apache/catalina/startup/ContextConfig.java
9a9096
--- java/org/apache/catalina/startup/ContextConfig.java.orig	2019-02-28 15:41:52.580345992 -0500
9a9096
+++ java/org/apache/catalina/startup/ContextConfig.java	2019-02-28 15:44:09.134930236 -0500
9a9096
@@ -433,15 +433,14 @@ public class ContextConfig implements Li
9a9096
         LoginConfig loginConfig = context.getLoginConfig();
9a9096
 
9a9096
         SecurityConstraint constraints[] = context.findConstraints();
9a9096
-        if (context.getIgnoreAnnotations() &&
9a9096
-                (constraints == null || constraints.length ==0) &&
9a9096
+        if ((constraints == null || constraints.length ==0) &&
9a9096
                 !context.getPreemptiveAuthentication())  {
9a9096
+            // No need for an authenticator
9a9096
             return;
9a9096
         } else {
9a9096
             if (loginConfig == null) {
9a9096
-                // Not metadata-complete or security constraints present, need
9a9096
-                // an authenticator to support @ServletSecurity annotations
9a9096
-                // and/or constraints
9a9096
+                // Security constraints present. Need an authenticator to
9a9096
+                // support them.
9a9096
                 loginConfig = DUMMY_LOGIN_CONFIG;
9a9096
                 context.setLoginConfig(loginConfig);
9a9096
             }
9a9096
diff -up java/org/apache/catalina/startup/Tomcat.java.orig java/org/apache/catalina/startup/Tomcat.java
9a9096
--- java/org/apache/catalina/startup/Tomcat.java.orig	2019-02-28 15:44:09.135930233 -0500
9a9096
+++ java/org/apache/catalina/startup/Tomcat.java	2019-02-28 15:47:52.376250650 -0500
9a9096
@@ -928,6 +928,9 @@ public class Tomcat {
9a9096
                 Context context = (Context) event.getLifecycle();
9a9096
                 if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
9a9096
                     context.setConfigured(true);
9a9096
+
9a9096
+                    // Process annotations
9a9096
+                    WebAnnotationSet.loadApplicationAnnotations(context);
9a9096
                 }
9a9096
                 // LoginConfig is required to process @ServletSecurity
9a9096
                 // annotations
9a9096
diff -up java/org/apache/catalina/startup/WebAnnotationSet.java.orig java/org/apache/catalina/startup/WebAnnotationSet.java
9a9096
--- java/org/apache/catalina/startup/WebAnnotationSet.java.orig	2017-03-09 08:51:40.000000000 -0500
9a9096
+++ java/org/apache/catalina/startup/WebAnnotationSet.java	2019-02-28 15:47:07.249388035 -0500
9a9096
@@ -23,10 +23,13 @@ import javax.annotation.Resource;
9a9096
 import javax.annotation.Resources;
9a9096
 import javax.annotation.security.DeclareRoles;
9a9096
 import javax.annotation.security.RunAs;
9a9096
+import javax.servlet.ServletSecurityElement;
9a9096
+import javax.servlet.annotation.ServletSecurity;
9a9096
 
9a9096
 import org.apache.catalina.Container;
9a9096
 import org.apache.catalina.Context;
9a9096
 import org.apache.catalina.Wrapper;
9a9096
+import org.apache.catalina.core.ApplicationServletRegistration;
9a9096
 import org.apache.catalina.deploy.ContextEnvironment;
9a9096
 import org.apache.catalina.deploy.ContextResource;
9a9096
 import org.apache.catalina.deploy.ContextResourceEnvRef;
9a9096
@@ -143,9 +146,17 @@ public class WebAnnotationSet {
9a9096
                  * Ref JSR 250, equivalent to the run-as element in
9a9096
                  * the deployment descriptor
9a9096
                  */
9a9096
-                RunAs annotation = classClass.getAnnotation(RunAs.class);
9a9096
-                if (annotation != null) {
9a9096
-                    wrapper.setRunAs(annotation.value());
9a9096
+                RunAs runAs = classClass.getAnnotation(RunAs.class);
9a9096
+                if (runAs != null) {
9a9096
+                    wrapper.setRunAs(runAs.value());
9a9096
+                }
9a9096
+
9a9096
+                // Process ServletSecurity annotation
9a9096
+                ServletSecurity servletSecurity = classClass.getAnnotation(ServletSecurity.class);
9a9096
+                if (servletSecurity != null) {
9a9096
+                    context.addServletSecurity(
9a9096
+                            new ApplicationServletRegistration(wrapper, context),
9a9096
+                            new ServletSecurityElement(servletSecurity));
9a9096
                 }
9a9096
             }
9a9096
         }
9a9096
diff -up java/org/apache/catalina/Wrapper.java.orig java/org/apache/catalina/Wrapper.java
9a9096
--- java/org/apache/catalina/Wrapper.java.orig	2019-02-28 15:41:52.554346071 -0500
9a9096
+++ java/org/apache/catalina/Wrapper.java	2019-02-28 15:44:09.129930251 -0500
9a9096
@@ -370,19 +370,23 @@ public interface Wrapper extends Contain
9a9096
     public void setEnabled(boolean enabled);
9a9096
 
9a9096
     /**
9a9096
-     * Set the flag that indicates
9a9096
-     * {@link javax.servlet.annotation.ServletSecurity} annotations must be
9a9096
-     * scanned when the Servlet is first used.
9a9096
+     * This method is no longer used. All implementations should be NO-OPs.
9a9096
      *
9a9096
-     * @param b The new value of the flag
9a9096
+     * @param b Unused.
9a9096
+     *
9a9096
+     * @deprecated This will be removed in Tomcat 9.
9a9096
      */
9a9096
+    @Deprecated
9a9096
     public void setServletSecurityAnnotationScanRequired(boolean b);
9a9096
 
9a9096
     /**
9a9096
-     * Scan for (if necessary) and process (if found) the
9a9096
-     * {@link javax.servlet.annotation.ServletSecurity} annotations for the
9a9096
-     * Servlet associated with this wrapper.
9a9096
+     * This method is no longer used. All implementations should be NO-OPs.
9a9096
+     *
9a9096
+     * @throws ServletException Never thrown
9a9096
+     *
9a9096
+     * @deprecated This will be removed in Tomcat 9.
9a9096
      */
9a9096
+    @Deprecated
9a9096
     public void servletSecurityAnnotationScan() throws ServletException;
9a9096
 
9a9096
     /**
9a9096
diff -up webapps/docs/changelog.xml.orig webapps/docs/changelog.xml
9a9096
--- webapps/docs/changelog.xml.orig	2019-02-28 15:41:52.591345958 -0500
9a9096
+++ webapps/docs/changelog.xml	2019-02-28 15:44:09.142930212 -0500
9a9096
@@ -68,6 +68,11 @@
9a9096
         <bug>62067</bug>: Correctly apply security constraints mapped to the
9a9096
         context root using a URL pattern of "". (markt)
9a9096
       </fix>
9a9096
+      <fix>
9a9096
+        Process all ServletSecurity annotations at web application
9a9096
+        start rather than at servlet load time to ensure constraints are applied
9a9096
+        consistently. (markt)
9a9096
+      </fix>
9a9096
     </changelog>
9a9096
   </subsection>
9a9096
 </section>
9a9096
commit c63b96d72cd39287e17b2ba698f4eee0ba508073
9a9096
Author: Mark Thomas <markt@apache.org>
9a9096
Date:   Thu Feb 15 20:21:56 2018 +0000
9a9096
9a9096
    Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=62104
9a9096
    Fix programmatic login regression as the NonLoginAuthenticator has to be set for it to work (if no login method is specified).
9a9096
    
9a9096
    git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk@1824360 13f79535-47bb-0310-9956-ffa450edef68
9a9096
9a9096
diff --git a/java/org/apache/catalina/startup/ContextConfig.java b/java/org/apache/catalina/startup/ContextConfig.java
9a9096
index d913b0e489..2d8aae0ff1 100644
9a9096
--- java/org/apache/catalina/startup/ContextConfig.java
9a9096
+++ java/org/apache/catalina/startup/ContextConfig.java
9a9096
@@ -431,19 +431,10 @@ public class ContextConfig implements LifecycleListener {
9a9096
     protected void authenticatorConfig() {
9a9096
 
9a9096
         LoginConfig loginConfig = context.getLoginConfig();
9a9096
-
9a9096
-        SecurityConstraint constraints[] = context.findConstraints();
9a9096
-        if ((constraints == null || constraints.length ==0) &&
9a9096
-                !context.getPreemptiveAuthentication())  {
9a9096
-            // No need for an authenticator
9a9096
-            return;
9a9096
-        } else {
9a9096
-            if (loginConfig == null) {
9a9096
-                // Security constraints present. Need an authenticator to
9a9096
-                // support them.
9a9096
-                loginConfig = DUMMY_LOGIN_CONFIG;
9a9096
-                context.setLoginConfig(loginConfig);
9a9096
-            }
9a9096
+        if (loginConfig == null) {
9a9096
+            // Need an authenticator to support HttpServletRequest.login()
9a9096
+            loginConfig = DUMMY_LOGIN_CONFIG;
9a9096
+            context.setLoginConfig(loginConfig);
9a9096
         }
9a9096
 
9a9096
         // Has an authenticator been configured already?
9a9096
diff -up webapps/docs/changelog.xml.orig webapps/docs/changelog.xml
9a9096
--- webapps/docs/changelog.xml.orig	2019-02-28 16:12:24.743968359 -0500
9a9096
+++ webapps/docs/changelog.xml	2019-02-28 16:12:39.412925943 -0500
9a9096
@@ -73,6 +73,11 @@
9a9096
         start rather than at servlet load time to ensure constraints are applied
9a9096
         consistently. (markt)
9a9096
       </fix>
9a9096
+      <fix>
9a9096
+        <bug>62104</bug>: Fix programmatic login regression as the
9a9096
+        NonLoginAuthenticator has to be set for it to work (if no login method
9a9096
+        is specified). (remm)
9a9096
+      </fix>
9a9096
     </changelog>
9a9096
   </subsection>
9a9096
 </section>