This is an automated email from the ASF dual-hosted git repository. rzo1 pushed a commit to branch tomee-9.x in repository https://gitbox.apache.org/repos/asf/tomee.git
commit 162054ced9356fb257f9da857479fd31cf3b40f9 Author: Richard Zowalla <[email protected]> AuthorDate: Tue Apr 18 13:32:45 2023 +0200 Patch Tomcat 10.0.27 for CVE-2023-24998 by applying the changeset from https://github.com/apache/tomcat/commit/8a2285f13affa961cc65595aad999db5efae45ce --- .../org/apache/catalina/connector/Request.java | 22 +++++++--- .../org/apache/tomcat/util/http/Parameters.java | 9 +++- .../util/http/fileupload/FileUploadBase.java | 39 ++++++++++++++--- .../impl/FileCountLimitExceededException.java | 50 ++++++++++++++++++++++ 4 files changed, 106 insertions(+), 14 deletions(-) diff --git a/tomee/apache-tomee/src/patch/java/org/apache/catalina/connector/Request.java b/tomee/apache-tomee/src/patch/java/org/apache/catalina/connector/Request.java index d867cdd554..55e7e677fa 100644 --- a/tomee/apache-tomee/src/patch/java/org/apache/catalina/connector/Request.java +++ b/tomee/apache-tomee/src/patch/java/org/apache/catalina/connector/Request.java @@ -1569,7 +1569,7 @@ public class Request implements HttpServletRequest { * @param oldValue Old attribute value */ private void notifyAttributeAssigned(String name, Object value, - Object oldValue) { + Object oldValue) { Context context = getContext(); if (context == null) { return; @@ -1671,7 +1671,7 @@ public class Request implements HttpServletRequest { @Override public ServletContext getServletContext() { return getContext().getServletContext(); - } + } @Override public AsyncContext startAsync() { @@ -1680,7 +1680,7 @@ public class Request implements HttpServletRequest { @Override public AsyncContext startAsync(ServletRequest request, - ServletResponse response) { + ServletResponse response) { if (!isAsyncSupported()) { IllegalStateException ise = new IllegalStateException(sm.getString("request.asyncNotSupported")); @@ -2041,7 +2041,7 @@ public class Request implements HttpServletRequest { handler = (T) instanceManager.newInstance(httpUpgradeHandlerClass); } } catch (ReflectiveOperationException | NamingException | IllegalArgumentException | - SecurityException e) { + SecurityException e) { throw new ServletException(e); } UpgradeToken upgradeToken = new UpgradeToken(handler, getContext(), instanceManager, @@ -2704,7 +2704,7 @@ public class Request implements HttpServletRequest { Session session = this.getSessionInternal(false); if (session == null) { throw new IllegalStateException( - sm.getString("coyoteRequest.changeSessionId")); + sm.getString("coyoteRequest.changeSessionId")); } Manager manager = this.getContext().getManager(); @@ -2840,8 +2840,9 @@ public class Request implements HttpServletRequest { } } + int maxParameterCount = getConnector().getMaxParameterCount(); Parameters parameters = coyoteRequest.getParameters(); - parameters.setLimit(getConnector().getMaxParameterCount()); + parameters.setLimit(maxParameterCount); boolean success = false; try { @@ -2893,6 +2894,13 @@ public class Request implements HttpServletRequest { upload.setFileItemFactory(factory); upload.setFileSizeMax(mce.getMaxFileSize()); upload.setSizeMax(mce.getMaxRequestSize()); + if (maxParameterCount > -1) { + // There is a limit. The limit for parts needs to be reduced by + // the number of parameters we have already parsed. + // Must be under the limit else parsing parameters would have + // triggered an exception. + upload.setFileCountMax(maxParameterCount - parameters.size()); + } parts = new ArrayList<>(); try { @@ -3544,7 +3552,7 @@ public class Request implements HttpServletRequest { public Object get(Request request, String name) { return Boolean.valueOf( request.getConnector().getProtocolHandler( - ).isSendfileSupported() && request.getCoyoteRequest().getSendfile()); + ).isSendfileSupported() && request.getCoyoteRequest().getSendfile()); } @Override public void set(Request request, String name, Object value) { diff --git a/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/Parameters.java b/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/Parameters.java index ce765374e7..bd86844b97 100644 --- a/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/Parameters.java +++ b/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/Parameters.java @@ -47,7 +47,7 @@ public final class Parameters { private static final UserDataHelper maxParamCountLog = new UserDataHelper(log); private static final StringManager sm = - StringManager.getManager("org.apache.tomcat.util.http"); + StringManager.getManager("org.apache.tomcat.util.http"); private final Map<String,ArrayList<String>> paramHashValues = new LinkedHashMap<>(); @@ -125,6 +125,11 @@ public final class Parameters { } + public int size() { + return parameterCount; + } + + public void recycle() { parameterCount = 0; paramHashValues.clear(); @@ -471,7 +476,7 @@ public final class Parameters { } private void urlDecode(ByteChunk bc) - throws IOException { + throws IOException { if( urlDec==null ) { urlDec=new UDecoder(); } diff --git a/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java b/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java index 7d678c24d8..ce903d489c 100644 --- a/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java +++ b/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java @@ -25,6 +25,7 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; +import org.apache.tomcat.util.http.fileupload.impl.FileCountLimitExceededException; import org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl; import org.apache.tomcat.util.http.fileupload.impl.FileUploadIOException; import org.apache.tomcat.util.http.fileupload.impl.IOFileUploadException; @@ -128,6 +129,12 @@ public abstract class FileUploadBase { */ private long fileSizeMax = -1; + /** + * The maximum permitted number of files that may be uploaded in a single + * request. A value of -1 indicates no maximum. + */ + private long fileCountMax = -1; + /** * The content encoding to use when reading part headers. */ @@ -204,6 +211,24 @@ public abstract class FileUploadBase { this.fileSizeMax = fileSizeMax; } + /** + * Returns the maximum number of files allowed in a single request. + * + * @return The maximum number of files allowed in a single request. + */ + public long getFileCountMax() { + return fileCountMax; + } + + /** + * Sets the maximum number of files allowed per request/ + * + * @param fileCountMax The new limit. {@code -1} means no limit. + */ + public void setFileCountMax(long fileCountMax) { + this.fileCountMax = fileCountMax; + } + /** * Retrieves the character encoding used when reading the headers of an * individual part. When not specified, or {@code null}, the request @@ -247,7 +272,7 @@ public abstract class FileUploadBase { * storing the uploaded content. */ public FileItemIterator getItemIterator(final RequestContext ctx) - throws FileUploadException, IOException { + throws FileUploadException, IOException { try { return new FileItemIteratorImpl(this, ctx); } catch (final FileUploadIOException e) { @@ -278,11 +303,15 @@ public abstract class FileUploadBase { "No FileItemFactory has been set."); final byte[] buffer = new byte[Streams.DEFAULT_BUFFER_SIZE]; while (iter.hasNext()) { + if (items.size() == fileCountMax) { + // The next item will exceed the limit. + throw new FileCountLimitExceededException(ATTACHMENT, getFileCountMax()); + } final FileItemStream item = iter.next(); // Don't use getName() here to prevent an InvalidFileNameException. final String fileName = item.getName(); final FileItem fileItem = fileItemFactory.createItem(item.getFieldName(), item.getContentType(), - item.isFormField(), fileName); + item.isFormField(), fileName); items.add(fileItem); try { Streams.copy(item.openStream(), fileItem.getOutputStream(), true, buffer); @@ -290,7 +319,7 @@ public abstract class FileUploadBase { throw (FileUploadException) e.getCause(); } catch (final IOException e) { throw new IOFileUploadException(String.format("Processing of %s request failed. %s", - MULTIPART_FORM_DATA, e.getMessage()), e); + MULTIPART_FORM_DATA, e.getMessage()), e); } final FileItemHeaders fih = item.getHeaders(); fileItem.setHeaders(fih); @@ -510,7 +539,7 @@ public abstract class FileUploadBase { final int offset = headerPart.indexOf('\r', index); if (offset == -1 || offset + 1 >= headerPart.length()) { throw new IllegalStateException( - "Expected headers to be terminated by an empty line."); + "Expected headers to be terminated by an empty line."); } if (headerPart.charAt(offset + 1) == '\n') { return offset; @@ -532,7 +561,7 @@ public abstract class FileUploadBase { } final String headerName = header.substring(0, colonOffset).trim(); final String headerValue = - header.substring(colonOffset + 1).trim(); + header.substring(colonOffset + 1).trim(); headers.addHeader(headerName, headerValue); } diff --git a/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/fileupload/impl/FileCountLimitExceededException.java b/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/fileupload/impl/FileCountLimitExceededException.java new file mode 100644 index 0000000000..958f681276 --- /dev/null +++ b/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/http/fileupload/impl/FileCountLimitExceededException.java @@ -0,0 +1,50 @@ +/* + * 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. + */ +package org.apache.tomcat.util.http.fileupload.impl; + +import org.apache.tomcat.util.http.fileupload.FileUploadException; + +/** + * This exception is thrown if a request contains more files than the specified + * limit. + */ +public class FileCountLimitExceededException extends FileUploadException { + + private static final long serialVersionUID = 2408766352570556046L; + + private final long limit; + + /** + * Creates a new instance. + * + * @param message The detail message + * @param limit The limit that was exceeded + */ + public FileCountLimitExceededException(final String message, final long limit) { + super(message); + this.limit = limit; + } + + /** + * Retrieves the limit that was exceeded. + * + * @return The limit that was exceeded by the request + */ + public long getLimit() { + return limit; + } +}
