Author: kkolinko Date: Thu Nov 10 08:44:03 2011 New Revision: 1200218 URL: http://svn.apache.org/viewvc?rev=1200218&view=rev Log: Merged revisions r1198696 r1198707 r1200056 r1200107 from tomcat/trunk: - Introduce new request attribute to be used to mark request if there was a failure during parameter parsing, - Implement FailedRequestFilter - a filter that triggers parameter parsing and rejects requests marked with that attribute. - Add sample configuration for FailedRequestFilter to conf/web.xml.
Added: tomcat/tc7.0.x/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java - copied, changed from r1198696, tomcat/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java Modified: tomcat/tc7.0.x/trunk/ (props changed) tomcat/tc7.0.x/trunk/conf/web.xml tomcat/tc7.0.x/trunk/java/org/apache/catalina/Globals.java tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/http/Parameters.java tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml tomcat/tc7.0.x/trunk/webapps/docs/config/filter.xml Propchange: tomcat/tc7.0.x/trunk/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Nov 10 08:44:03 2011 @@ -1 +1 @@ -/tomcat/trunk:1156115,1156171,1156276,1156304,1156519,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366,1166620,1166686,1166693,1166752,1166757,1167368,1167394,1169447,1170647,1171692,1172233-1172234,1172236,1172269,1172278,1172282,1172556,1172610,1172664,1172689,1172711,1173020-1173021,1173082,1173088,1173090,1173096 ,1173241,1173256,1173288,1173333,1173342,1173461,1173614,1173630,1173659,1173722,1174061,1174239,1174322,1174325,1174329-1174330,1174337-1174339,1174343,1174353,1174799,1174882,1174884,1174983,1175155,1175158,1175167,1175182,1175190,1175201,1175272,1175275,1175283,1175582,1175589-1175590,1175594,1175602,1175613,1175633,1175690,1175713,1175798,1175889,1175896,1175907,1176584,1176590,1176799,1177050,1177060,1177125,1177152,1177160,1177245,1177850,1177862,1177978,1178209,1178228,1178233,1178449,1178542,1178681,1178684,1178721,1179268,1179274,1180261,1180865,1180891,1180894,1180907,1181028,1181123,1181125,1181136,1181291,1181743,1182796,1183078,1183105,1183142,1183328,1183339-1183340,1183492-1183494,1183605,1184917,1184919,1185018,1185020,1185200,1185588,1185626,1185756,1185758,1186011,1186042-1186045,1186104,1186123,1186137,1186153,1186254,1186257,1186377-1186379,1186479-1186480,1186712,1186743,1186750,1186763,1186890-1186892,1186894,1186949,1187018,1187027-1187028,1187381,1187 753,1187755,1187775,1187801,1187806,1187809,1187827,1188301,1188303-1188305,1188399,1188822,1188930-1188931,1189116,1189129,1189183,1189240,1189256,1189386,1189413-1189414,1189477,1189685,1189805,1189857,1189864,1189882,1190034,1190185,1190279,1190339,1190371,1190388-1190389,1190474,1190481,1194915,1195222-1195223,1195531,1195899,1195905,1195943,1195949,1195953,1195955,1195965,1195968,1196175,1196212,1196223,1196304-1196305,1196735,1196825,1196827,1197158,1197261,1197263,1197299-1197300,1197305,1197339-1197340,1197343,1197382,1197386-1197387,1197480,1197578,1198497,1198528,1198552,1198602,1198604,1198607,1198622,1198640,1199418,1199432,1199436,1199513,1199529,1199980,1199996,1200106 +/tomcat/trunk:1156115,1156171,1156276,1156304,1156519,1156530,1156602,1157015,1157018,1157151,1157198,1157204,1157810,1157832,1157834,1157847,1157908,1157939,1158155,1158160,1158176,1158195,1158198-1158199,1158227,1158331,1158334-1158335,1158426,1160347,1160592,1160611,1160619,1160626,1160639,1160652,1160720-1160721,1160772,1160774,1160776,1161303,1161310,1161322,1161339,1161486,1161540,1161549,1161584,1162082,1162149,1162169,1162721,1162769,1162836,1162932,1163630,1164419,1164438,1164469,1164480,1164567,1165234,1165247-1165248,1165253,1165273,1165282,1165309,1165331,1165338,1165347,1165360-1165361,1165367-1165368,1165602,1165608,1165677,1165693,1165721,1165723,1165728,1165730,1165738,1165746,1165765,1165777,1165918,1165921,1166077,1166150-1166151,1166290,1166366,1166620,1166686,1166693,1166752,1166757,1167368,1167394,1169447,1170647,1171692,1172233-1172234,1172236,1172269,1172278,1172282,1172556,1172610,1172664,1172689,1172711,1173020-1173021,1173082,1173088,1173090,1173096 ,1173241,1173256,1173288,1173333,1173342,1173461,1173614,1173630,1173659,1173722,1174061,1174239,1174322,1174325,1174329-1174330,1174337-1174339,1174343,1174353,1174799,1174882,1174884,1174983,1175155,1175158,1175167,1175182,1175190,1175201,1175272,1175275,1175283,1175582,1175589-1175590,1175594,1175602,1175613,1175633,1175690,1175713,1175798,1175889,1175896,1175907,1176584,1176590,1176799,1177050,1177060,1177125,1177152,1177160,1177245,1177850,1177862,1177978,1178209,1178228,1178233,1178449,1178542,1178681,1178684,1178721,1179268,1179274,1180261,1180865,1180891,1180894,1180907,1181028,1181123,1181125,1181136,1181291,1181743,1182796,1183078,1183105,1183142,1183328,1183339-1183340,1183492-1183494,1183605,1184917,1184919,1185018,1185020,1185200,1185588,1185626,1185756,1185758,1186011,1186042-1186045,1186104,1186123,1186137,1186153,1186254,1186257,1186377-1186379,1186479-1186480,1186712,1186743,1186750,1186763,1186890-1186892,1186894,1186949,1187018,1187027-1187028,1187381,1187 753,1187755,1187775,1187801,1187806,1187809,1187827,1188301,1188303-1188305,1188399,1188822,1188930-1188931,1189116,1189129,1189183,1189240,1189256,1189386,1189413-1189414,1189477,1189685,1189805,1189857,1189864,1189882,1190034,1190185,1190279,1190339,1190371,1190388-1190389,1190474,1190481,1194915,1195222-1195223,1195531,1195899,1195905,1195943,1195949,1195953,1195955,1195965,1195968,1196175,1196212,1196223,1196304-1196305,1196735,1196825,1196827,1197158,1197261,1197263,1197299-1197300,1197305,1197339-1197340,1197343,1197382,1197386-1197387,1197480,1197578,1198497,1198528,1198552,1198602,1198604,1198607,1198622,1198640,1198696,1198707,1199418,1199432,1199436,1199513,1199529,1199980,1199996,1200056,1200106-1200107 Modified: tomcat/tc7.0.x/trunk/conf/web.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/conf/web.xml?rev=1200218&r1=1200217&r2=1200218&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/conf/web.xml (original) +++ tomcat/tc7.0.x/trunk/conf/web.xml Thu Nov 10 08:44:03 2011 @@ -388,6 +388,20 @@ <!-- ================== Built In Filter Definitions ===================== --> + <!-- A filter that triggers request parameters parsing and rejects the --> + <!-- request if some parameters were skipped because of parsing errors or --> + <!-- request size limitations. --> +<!-- + <filter> + <filter-name>failedRequestFilter</filter-name> + <filter-class> + org.apache.catalina.filters.FailedRequestFilter + </filter-class> + <async-supported>true</async-supported> + </filter> +--> + + <!-- NOTE: An SSI Servlet is also available as an alternative SSI --> <!-- implementation. Use either the Servlet or the Filter but NOT both. --> <!-- --> @@ -448,6 +462,14 @@ <!-- ==================== Built In Filter Mappings ====================== --> + <!-- The mapping for the Failed Request Filter --> +<!-- + <filter-mapping> + <filter-name>failedRequestFilter</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> +--> + <!-- The mapping for the SSI Filter --> <!-- <filter-mapping> Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/Globals.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/Globals.java?rev=1200218&r1=1200217&r2=1200218&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/catalina/Globals.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/Globals.java Thu Nov 10 08:44:03 2011 @@ -162,6 +162,17 @@ public final class Globals { /** + * The request attribute that is set to {@code Boolean.TRUE} if some request + * parameters have been ignored during request parameters parsing. It can + * happen, for example, if there is a limit on the total count of parseable + * parameters, or if parameter cannot be decoded, or any other error + * happened during parameter parsing. + */ + public static final String PARAMETER_PARSE_FAILED_ATTR = + "org.apache.catalina.parameter_parse_failed"; + + + /** * The master flag which controls strict servlet specification * compliance. */ Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java?rev=1200218&r1=1200217&r2=1200218&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/connector/Request.java Thu Nov 10 08:44:03 2011 @@ -947,6 +947,13 @@ public class Request return null; } + if (name.equals(Globals.PARAMETER_PARSE_FAILED_ATTR)) { + if (coyoteRequest.getParameters().isParseFailed()) { + return Boolean.TRUE; + } + return null; + } + Object attr=attributes.get(name); if(attr!=null) { @@ -1018,6 +1025,7 @@ public class Request * <li>{@link Globals#SSL_SESSION_ID_TOMCAT_ATTR} (SSL connections only) * </li> * <li>{@link Globals#SSL_SESSION_MGR_ATTR} (SSL connections only)</li> + * <li>{@link Globals#PARAMETER_PARSE_FAILED_ATTR}</li> * </ul> * The underlying connector may also expose request attributes. These all * have names starting with "org.apache.tomcat" and include: @@ -2684,109 +2692,116 @@ public class Request Parameters parameters = coyoteRequest.getParameters(); - File location; - String locationStr = mce.getLocation(); - if (locationStr == null || locationStr.length() == 0) { - location = ((File) context.getServletContext().getAttribute( - ServletContext.TEMPDIR)); - } else { - location = new File(locationStr); - } - - if (!location.isAbsolute() || !location.isDirectory()) { - partsParseException = new IOException( - sm.getString("coyoteRequest.uploadLocationInvalid", - location)); - return; - } - - // Create a new file upload handler - DiskFileItemFactory factory = new DiskFileItemFactory(); + boolean success = false; try { - factory.setRepository(location.getCanonicalFile()); - } catch (IOException ioe) { - partsParseException = ioe; - return; - } - factory.setSizeThreshold(mce.getFileSizeThreshold()); + File location; + String locationStr = mce.getLocation(); + if (locationStr == null || locationStr.length() == 0) { + location = ((File) context.getServletContext().getAttribute( + ServletContext.TEMPDIR)); + } else { + location = new File(locationStr); + } - ServletFileUpload upload = new ServletFileUpload(); - upload.setFileItemFactory(factory); - upload.setFileSizeMax(mce.getMaxFileSize()); - upload.setSizeMax(mce.getMaxRequestSize()); + if (!location.isAbsolute() || !location.isDirectory()) { + partsParseException = new IOException( + sm.getString("coyoteRequest.uploadLocationInvalid", + location)); + return; + } - parts = new ArrayList<Part>(); - try { - List<FileItem> items = upload.parseRequest(this); - int maxPostSize = getConnector().getMaxPostSize(); - int postSize = 0; - String enc = getCharacterEncoding(); - Charset charset = null; - if (enc != null) { - try { - charset = B2CConverter.getCharset(enc); - } catch (UnsupportedEncodingException e) { - // Ignore - } + + // Create a new file upload handler + DiskFileItemFactory factory = new DiskFileItemFactory(); + try { + factory.setRepository(location.getCanonicalFile()); + } catch (IOException ioe) { + partsParseException = ioe; + return; } - for (FileItem item : items) { - ApplicationPart part = new ApplicationPart(item, mce); - parts.add(part); - if (part.getFilename() == null) { - String name = part.getName(); - String value = null; + factory.setSizeThreshold(mce.getFileSizeThreshold()); + + ServletFileUpload upload = new ServletFileUpload(); + upload.setFileItemFactory(factory); + upload.setFileSizeMax(mce.getMaxFileSize()); + upload.setSizeMax(mce.getMaxRequestSize()); + + parts = new ArrayList<Part>(); + try { + List<FileItem> items = upload.parseRequest(this); + int maxPostSize = getConnector().getMaxPostSize(); + int postSize = 0; + String enc = getCharacterEncoding(); + Charset charset = null; + if (enc != null) { try { - String encoding = parameters.getEncoding(); - if (encoding == null) { - encoding = Parameters.DEFAULT_ENCODING; - } - value = part.getString(encoding); - } catch (UnsupportedEncodingException uee) { - try { - value = part.getString(Parameters.DEFAULT_ENCODING); - } catch (UnsupportedEncodingException e) { - // Should not be possible - } + charset = B2CConverter.getCharset(enc); + } catch (UnsupportedEncodingException e) { + // Ignore } - if (maxPostSize > 0) { - // Have to calculate equivalent size. Not completely - // accurate but close enough. - if (charset == null) { - // Name length - postSize += name.getBytes().length; - } else { - postSize += name.getBytes(charset).length; + } + for (FileItem item : items) { + ApplicationPart part = new ApplicationPart(item, mce); + parts.add(part); + if (part.getFilename() == null) { + String name = part.getName(); + String value = null; + try { + String encoding = parameters.getEncoding(); + if (encoding == null) { + encoding = Parameters.DEFAULT_ENCODING; + } + value = part.getString(encoding); + } catch (UnsupportedEncodingException uee) { + try { + value = part.getString(Parameters.DEFAULT_ENCODING); + } catch (UnsupportedEncodingException e) { + // Should not be possible + } } - if (value != null) { - // Equals sign + if (maxPostSize > 0) { + // Have to calculate equivalent size. Not completely + // accurate but close enough. + if (charset == null) { + // Name length + postSize += name.getBytes().length; + } else { + postSize += name.getBytes(charset).length; + } + if (value != null) { + // Equals sign + postSize++; + // Value length + postSize += part.getSize(); + } + // Value separator postSize++; - // Value length - postSize += part.getSize(); - } - // Value separator - postSize++; - if (postSize > maxPostSize) { - throw new IllegalStateException(sm.getString( - "coyoteRequest.maxPostSizeExceeded")); + if (postSize > maxPostSize) { + throw new IllegalStateException(sm.getString( + "coyoteRequest.maxPostSizeExceeded")); + } } + parameters.addParameter(name, value); } - parameters.addParameter(name, value); } - } - } catch (InvalidContentTypeException e) { - partsParseException = new ServletException(e); - } catch (FileUploadBase.SizeException e) { - checkSwallowInput(); - partsParseException = new IllegalStateException(e); - } catch (FileUploadException e) { - partsParseException = new IOException(e); - } catch (IllegalStateException e) { - checkSwallowInput(); - partsParseException = e; + success = true; + } catch (InvalidContentTypeException e) { + partsParseException = new ServletException(e); + } catch (FileUploadBase.SizeException e) { + checkSwallowInput(); + partsParseException = new IllegalStateException(e); + } catch (FileUploadException e) { + partsParseException = new IOException(e); + } catch (IllegalStateException e) { + checkSwallowInput(); + partsParseException = e; + } + } finally { + if (partsParseException != null || !success) { + parameters.setParseFailed(true); + } } - - return; } @@ -2971,107 +2986,119 @@ public class Request parametersParsed = true; Parameters parameters = coyoteRequest.getParameters(); - // Set this every time in case limit has been changed via JMX - parameters.setLimit(getConnector().getMaxParameterCount()); + boolean success = false; + try { + // Set this every time in case limit has been changed via JMX + parameters.setLimit(getConnector().getMaxParameterCount()); - // getCharacterEncoding() may have been overridden to search for - // hidden form field containing request encoding - String enc = getCharacterEncoding(); - - boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI(); - if (enc != null) { - parameters.setEncoding(enc); - if (useBodyEncodingForURI) { - parameters.setQueryStringEncoding(enc); - } - } else { - parameters.setEncoding - (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING); - if (useBodyEncodingForURI) { - parameters.setQueryStringEncoding + // getCharacterEncoding() may have been overridden to search for + // hidden form field containing request encoding + String enc = getCharacterEncoding(); + + boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI(); + if (enc != null) { + parameters.setEncoding(enc); + if (useBodyEncodingForURI) { + parameters.setQueryStringEncoding(enc); + } + } else { + parameters.setEncoding (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING); + if (useBodyEncodingForURI) { + parameters.setQueryStringEncoding + (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING); + } } - } - parameters.handleQueryParameters(); + parameters.handleQueryParameters(); - if (usingInputStream || usingReader) { - return; - } + if (usingInputStream || usingReader) { + success = true; + return; + } - if( !getConnector().isParseBodyMethod(getMethod()) ) { - return; - } + if( !getConnector().isParseBodyMethod(getMethod()) ) { + success = true; + return; + } - String contentType = getContentType(); - if (contentType == null) { - contentType = ""; - } - int semicolon = contentType.indexOf(';'); - if (semicolon >= 0) { - contentType = contentType.substring(0, semicolon).trim(); - } else { - contentType = contentType.trim(); - } + String contentType = getContentType(); + if (contentType == null) { + contentType = ""; + } + int semicolon = contentType.indexOf(';'); + if (semicolon >= 0) { + contentType = contentType.substring(0, semicolon).trim(); + } else { + contentType = contentType.trim(); + } - if ("multipart/form-data".equals(contentType)) { - parseParts(); - return; - } + if ("multipart/form-data".equals(contentType)) { + parseParts(); + success = true; + return; + } - if (!("application/x-www-form-urlencoded".equals(contentType))) { - return; - } + if (!("application/x-www-form-urlencoded".equals(contentType))) { + success = true; + return; + } - int len = getContentLength(); + int len = getContentLength(); - if (len > 0) { - int maxPostSize = connector.getMaxPostSize(); - if ((maxPostSize > 0) && (len > maxPostSize)) { - if (context.getLogger().isDebugEnabled()) { - context.getLogger().debug( - sm.getString("coyoteRequest.postTooLarge")); + if (len > 0) { + int maxPostSize = connector.getMaxPostSize(); + if ((maxPostSize > 0) && (len > maxPostSize)) { + if (context.getLogger().isDebugEnabled()) { + context.getLogger().debug( + sm.getString("coyoteRequest.postTooLarge")); + } + checkSwallowInput(); + return; } - checkSwallowInput(); - return; - } - byte[] formData = null; - if (len < CACHED_POST_LEN) { - if (postData == null) { - postData = new byte[CACHED_POST_LEN]; + byte[] formData = null; + if (len < CACHED_POST_LEN) { + if (postData == null) { + postData = new byte[CACHED_POST_LEN]; + } + formData = postData; + } else { + formData = new byte[len]; } - formData = postData; - } else { - formData = new byte[len]; - } - try { - if (readPostBody(formData, len) != len) { + try { + if (readPostBody(formData, len) != len) { + return; + } + } catch (IOException e) { + // Client disconnect + if (context.getLogger().isDebugEnabled()) { + context.getLogger().debug( + sm.getString("coyoteRequest.parseParameters"), e); + } return; } - } catch (IOException e) { - // Client disconnect - if (context.getLogger().isDebugEnabled()) { - context.getLogger().debug( - sm.getString("coyoteRequest.parseParameters"), e); + parameters.processParameters(formData, 0, len); + } else if ("chunked".equalsIgnoreCase( + coyoteRequest.getHeader("transfer-encoding"))) { + byte[] formData = null; + try { + formData = readChunkedPostBody(); + } catch (IOException e) { + // Client disconnect + if (context.getLogger().isDebugEnabled()) { + context.getLogger().debug( + sm.getString("coyoteRequest.parseParameters"), e); + } + return; } - return; - } - parameters.processParameters(formData, 0, len); - } else if ("chunked".equalsIgnoreCase( - coyoteRequest.getHeader("transfer-encoding"))) { - byte[] formData = null; - try { - formData = readChunkedPostBody(); - } catch (IOException e) { - // Client disconnect - if (context.getLogger().isDebugEnabled()) { - context.getLogger().debug( - sm.getString("coyoteRequest.parseParameters"), e); + if (formData != null) { + parameters.processParameters(formData, 0, formData.length); } - return; } - if (formData != null) { - parameters.processParameters(formData, 0, formData.length); + success = true; + } finally { + if (!success) { + parameters.setParseFailed(true); } } Copied: tomcat/tc7.0.x/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java (from r1198696, tomcat/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java) URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java?p2=tomcat/tc7.0.x/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java&p1=tomcat/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java&r1=1198696&r2=1200218&rev=1200218&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/filters/FailedRequestFilter.java Thu Nov 10 08:44:03 2011 @@ -38,9 +38,10 @@ import org.apache.juli.logging.LogFactor * * <p> * Note that it has side effect that it triggers parameter parsing and thus - * consumes the body for POST requests, so use it only with addresses that do not - * use <code>request.getInputStream()</code> and - * <code>request.getReader()</code>. + * consumes the body for POST requests. Parameter parsing does check content + * type of the request, so there should not be problems with addresses that use + * <code>request.getInputStream()</code> and <code>request.getReader()</code>, + * if requests parsed by them do not use standard value for content mime-type. */ public class FailedRequestFilter extends FilterBase implements CometFilter { Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/http/Parameters.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/http/Parameters.java?rev=1200218&r1=1200217&r2=1200218&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/http/Parameters.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/http/Parameters.java Thu Nov 10 08:44:03 2011 @@ -60,6 +60,12 @@ public final class Parameters { private int limit = -1; private int parameterCount = 0; + /** + * Is set to <code>true</code> if there were failures during parameter + * parsing. + */ + private boolean parseFailed = false; + public Parameters() { // NO-OP } @@ -90,12 +96,21 @@ public final class Parameters { } } + public boolean isParseFailed() { + return parseFailed; + } + + public void setParseFailed(boolean parseFailed) { + this.parseFailed = parseFailed; + } + public void recycle() { parameterCount = 0; paramHashValues.clear(); didQueryParameters=false; encoding=null; decodedQuery.recycle(); + parseFailed = false; } // -------------------- Data access -------------------- @@ -186,6 +201,7 @@ public final class Parameters { if (limit > -1 && parameterCount > limit) { // Processing this parameter will push us over the limit. ISE is // what Request.parseParts() uses for requests that are too big + parseFailed = true; throw new IllegalStateException(sm.getString( "parameters.maxCountFail", Integer.valueOf(limit))); } @@ -314,6 +330,7 @@ public final class Parameters { null)); } } + parseFailed = true; continue; // invalid chunk - it's better to ignore } @@ -355,10 +372,12 @@ public final class Parameters { } catch (IllegalStateException ise) { // Hitting limit stops processing further params but does // not cause request to fail. + parseFailed = true; log.warn(ise.getMessage()); break; } } catch (IOException e) { + parseFailed = true; decodeFailCount++; if (decodeFailCount == 1 || log.isDebugEnabled()) { if (log.isDebugEnabled()) { 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=1200218&r1=1200217&r2=1200218&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Thu Nov 10 08:44:03 2011 @@ -163,7 +163,9 @@ <add> Improve performance of parameter processing for GET and POST requests. Also add an option to limit the maximum number of parameters processed - per request. This defaults to 10000. (markt/kkolinko) + per request. This defaults to 10000. Excessive parameters are ignored. + Note that <code>FailedRequestFilter</code> can be used to reject the + request if some parameters were ignored. (markt/kkolinko) </add> <fix> <bug>52091</bug>: Address performance issues related to lock contention @@ -189,6 +191,15 @@ resource when path contains <code>/../</code> sequences or any other sequences that require normalization. (markt) </fix> + <add> + Report existence of HTTP request parameter parsing errors via new + special ServletRequest attribute, + <code>org.apache.catalina.parameter_parse_failed</code>. (kkolinko) + </add> + <add> + New filter <code>FailedRequestFilter</code> that will reject a request + if there were errors during HTTP parameter parsing. (kkolinko) + </add> </changelog> </subsection> <subsection name="Coyote"> Modified: tomcat/tc7.0.x/trunk/webapps/docs/config/filter.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/config/filter.xml?rev=1200218&r1=1200217&r2=1200218&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/config/filter.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/config/filter.xml Thu Nov 10 08:44:03 2011 @@ -1207,6 +1207,44 @@ org.apache.catalina.filters.RequestDumpe </section> +<section name="Failed Request Filter"> + + <subsection name="Introduction"> + + <p>This filter triggers parameters parsing in a request and rejects the + request if some parameters were skipped during parameter parsing because + of parsing errors or request size limitations (such as + <code>maxParameterCount</code> attribute in a + <a href="http.html">Connector</a>). + This filter can be used to ensure that none parameter values submitted by + client are lost.</p> + + <p>Note that parameter parsing may consume the body of an HTTP request, so + caution is needed if the servlet protected by this filter uses + <code>request.getInputStream()</code> or <code>request.getReader()</code> + calls. In general the risk of breaking a web application by adding this + filter is not so high, because parameter parsing does check content type + of the request before consuming the request body.</p> + + </subsection> + + <subsection name="Filter Class Name"> + + <p>The filter class name for the Failed Request Filter is + <strong><code>org.apache.catalina.filters.FailedRequestFilter</code> + </strong>.</p> + + </subsection> + + <subsection name="Initialisation parameters"> + + <p>The Failed Request Filter does not support any initialization parameters.</p> + + </subsection> + +</section> + + </body> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org