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