Author: markt Date: Wed Jun 19 21:43:26 2013 New Revision: 1494779 URL: http://svn.apache.org/r1494779 Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=53987 Servlet 3.1. Log uncovered HTTP methods.
Modified: tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Modified: tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties?rev=1494779&r1=1494778&r2=1494779&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/core/LocalStrings.properties Wed Jun 19 21:43:26 2013 @@ -139,6 +139,8 @@ standardContext.servletMap.pattern=Inval standardContext.startFailed=Context [{0}] startup failed due to previous errors standardContext.startingContext=Exception starting Context with name [{0}] standardContext.stoppingContext=Exception stopping Context with name [{0}] +standardContext.uncoveredHttpMethod=For security constraints with URL pattern [{0}] only the HTTP methods [{1}] are covered. All other methods are uncovered. +standardContext.uncoveredHttpOmittedMethod=For security constraints with URL pattern [{0}] the HTTP methods [{1}] are uncovered. standardContext.urlPattern.patternWarning=WARNING: URL pattern {0} must start with a ''/'' in Servlet 2.4 standardContext.webappClassLoader.missingProperty=Unable to set the web application class loader property [{0}] to [{1}] as the property does not exist. standardContext.workPath=Exception obtaining work path for context [{0}] 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=1494779&r1=1494778&r2=1494779&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Wed Jun 19 21:43:26 2013 @@ -5271,6 +5271,13 @@ public class StandardContext extends Con } } + // Check constraints for uncovered HTTP methods + // Needs to be after SCIs and listeners as they may programatically + // change constraints + if (ok) { + checkConstraintsForUncoveredMethods(); + } + try { // Start manager Manager manager = getManager(); @@ -5334,6 +5341,107 @@ public class StandardContext extends Con } } + + private void checkConstraintsForUncoveredMethods() { + // TODO - Add an option to lower the log level of any uncovered method + // warnings to debug + // TODO - Implement adding constraints to deny uncovered methods + Set<String> coveredPatterns = new HashSet<>(); + Map<String,Set<String>> urlMethodMap = new HashMap<>(); + Map<String,Set<String>> urlOmittedMethodMap = new HashMap<>(); + + // First build the lists of covered patterns and those patterns that + // might be uncovered + for (SecurityConstraint constraint : constraints) { + SecurityCollection[] collections = constraint.findCollections(); + for (SecurityCollection collection : collections) { + String[] patterns = collection.findPatterns(); + String[] methods = collection.findMethods(); + String[] omittedMethods = collection.findOmittedMethods(); + // Simple case: no methods + if (methods.length == 0 && omittedMethods.length == 0) { + for (String pattern : patterns) { + coveredPatterns.add(pattern); + } + continue; + } + + // Pre-calculate so we don't do this for every iteration of the + // following loop + List<String> omNew = null; + if (omittedMethods.length == 0) { + omNew = Arrays.asList(omittedMethods); + } + + // Only need to process uncovered patterns + for (String pattern : patterns) { + if (!coveredPatterns.contains(pattern)) { + if (methods.length == 0) { + // Build the interset of omitted methods for this + // pattern + Set<String> om = urlOmittedMethodMap.get(pattern); + if (om == null) { + om = new HashSet<>(); + urlMethodMap.put(pattern, om); + } + om.retainAll(omNew); + } else { + // Build the union of methods for this pattern + Set<String> m = urlMethodMap.get(pattern); + if (m == null) { + m = new HashSet<>(); + urlMethodMap.put(pattern, m); + } + for (String method : methods) { + m.add(method); + } + } + } + } + } + } + + // Now check the potentially uncovered patterns + for (Map.Entry<String, Set<String>> entry : urlMethodMap.entrySet()) { + String pattern = entry.getKey(); + if (coveredPatterns.contains(pattern)) { + // Fully covered. Ignore any partial coverage + urlOmittedMethodMap.remove(pattern); + continue; + } + + Set<String> omittedMethods = urlOmittedMethodMap.get(pattern); + Set<String> methods = entry.getValue(); + + if (omittedMethods == null) { + StringBuilder msg = new StringBuilder(); + for (String method : methods) { + msg.append(method); + msg.append(' '); + } + log.error(sm.getString("standardContext.uncoveredHttpMethod", + pattern, msg.toString().trim())); + continue; + } + + // As long as every omitted method as a corresponding method the + // pattern is fully covered. + omittedMethods.removeAll(methods); + + if (omittedMethods.size() > 0) { + StringBuilder msg = new StringBuilder(); + for (String method : omittedMethods) { + msg.append(method); + msg.append(' '); + } + log.error(sm.getString( + "standardContext.uncoveredHttpOmittedMethod", + pattern, msg.toString().trim())); + } + } + } + + private void setClassLoaderProperty(String name, boolean value) { ClassLoader cl = getLoader().getClassLoader(); if (!IntrospectionUtils.setProperty(cl, name, Boolean.toString(value))) { --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org