From ebb0431a510b8cb779ec03c9e47245aef30d701c Mon Sep 17 00:00:00 2001 From: wk333 <13474090681@163.com> Date: Wed, 18 Dec 2024 10:49:32 +0800 Subject: [PATCH] Fix CVE-2024-50379 CVE-2024-54677 (cherry picked from commit 37b6fbcf4c334035b8423e43c24b2bea2397c27f) --- CVE-2024-50379-1.patch | 435 ++++++++++++++++++++++++ CVE-2024-50379-2.patch | 32 ++ CVE-2024-54677-1.patch | 48 +++ CVE-2024-54677-2.patch | 61 ++++ CVE-2024-54677-3.patch | 137 ++++++++ CVE-2024-54677-4.patch | 31 ++ CVE-2024-54677-5.patch | 97 ++++++ CVE-2024-54677-6.patch | 23 ++ CVE-2024-54677-7.patch | 270 +++++++++++++++ CVE-2024-54677-8.patch | 717 +++++++++++++++++++++++++++++++++++++++ CVE-2024-54677-9.patch | 22 ++ CVE-2024-54677-pre.patch | 440 ++++++++++++++++++++++++ tomcat.spec | 17 +- 13 files changed, 2329 insertions(+), 1 deletion(-) create mode 100644 CVE-2024-50379-1.patch create mode 100644 CVE-2024-50379-2.patch create mode 100644 CVE-2024-54677-1.patch create mode 100644 CVE-2024-54677-2.patch create mode 100644 CVE-2024-54677-3.patch create mode 100644 CVE-2024-54677-4.patch create mode 100644 CVE-2024-54677-5.patch create mode 100644 CVE-2024-54677-6.patch create mode 100644 CVE-2024-54677-7.patch create mode 100644 CVE-2024-54677-8.patch create mode 100644 CVE-2024-54677-9.patch create mode 100644 CVE-2024-54677-pre.patch diff --git a/CVE-2024-50379-1.patch b/CVE-2024-50379-1.patch new file mode 100644 index 0000000..d8022bc --- /dev/null +++ b/CVE-2024-50379-1.patch @@ -0,0 +1,435 @@ +From 43b507ebac9d268b1ea3d908e296cc6e46795c00 Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Fri, 1 Nov 2024 16:35:17 +0000 +Subject: [PATCH] Fix inconsistent resource metadata with current GET and + PUT/DELETE +Origin: https://github.com/apache/tomcat/commit/43b507ebac9d268b1ea3d908e296cc6e46795c00 + +Concurrent reads and writes (e.g. HTTP GET and PUT / DELETE) for the +same path cause corruption of the FileResource where some of the fields +are set as if the file exists and some as set as if it does not. +--- + .../apache/catalina/WebResourceLockSet.java | 73 +++++++ + .../catalina/webresources/DirResourceSet.java | 199 +++++++++++++++--- + .../catalina/webresources/FileResource.java | 29 ++- + .../webresources/LocalStrings.properties | 1 + + 4 files changed, 273 insertions(+), 29 deletions(-) + create mode 100644 java/org/apache/catalina/WebResourceLockSet.java + +diff --git a/java/org/apache/catalina/WebResourceLockSet.java b/java/org/apache/catalina/WebResourceLockSet.java +new file mode 100644 +index 000000000000..142472c33cd6 +--- /dev/null ++++ b/java/org/apache/catalina/WebResourceLockSet.java +@@ -0,0 +1,73 @@ ++/* ++ * 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.catalina; ++ ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.concurrent.locks.ReentrantReadWriteLock; ++ ++/** ++ * Interface implemented by {@link WebResourceSet} implementations that wish to provide locking functionality. ++ */ ++public interface WebResourceLockSet { ++ ++ /** ++ * Lock the resource at the provided path for reading. The resource is not required to exist. Read locks are not ++ * exclusive. ++ * ++ * @param path The path to the resource to be locked for reading ++ * ++ * @return The {@link ResourceLock} that must be passed to {@link #unlockForRead(ResourceLock)} to release the lock ++ */ ++ ResourceLock lockForRead(String path); ++ ++ /** ++ * Release a read lock from the resource associated with the given {@link ResourceLock}. ++ * ++ * @param resourceLock The {@link ResourceLock} associated with the resource for which a read lock should be ++ * released ++ */ ++ void unlockForRead(ResourceLock resourceLock); ++ ++ /** ++ * Lock the resource at the provided path for writing. The resource is not required to exist. Write locks are ++ * exclusive. ++ * ++ * @param path The path to the resource to be locked for writing ++ * ++ * @return The {@link ResourceLock} that must be passed to {@link #unlockForWrite(ResourceLock)} to release the lock ++ */ ++ ResourceLock lockForWrite(String path); ++ ++ /** ++ * Release the write lock from the resource associated with the given {@link ResourceLock}. ++ * ++ * @param resourceLock The {@link ResourceLock} associated with the resource for which the write lock should be ++ * released ++ */ ++ void unlockForWrite(ResourceLock resourceLock); ++ ++ ++ class ResourceLock { ++ public final AtomicInteger count = new AtomicInteger(0); ++ public final ReentrantReadWriteLock reentrantLock = new ReentrantReadWriteLock(); ++ public final String key; ++ ++ public ResourceLock(String key) { ++ this.key = key; ++ } ++ } ++} +diff --git a/java/org/apache/catalina/webresources/DirResourceSet.java b/java/org/apache/catalina/webresources/DirResourceSet.java +index a221c3f1c33d..02ddc6ec887c 100644 +--- a/java/org/apache/catalina/webresources/DirResourceSet.java ++++ b/java/org/apache/catalina/webresources/DirResourceSet.java +@@ -22,24 +22,35 @@ + import java.io.InputStream; + import java.nio.file.Files; + import java.nio.file.StandardCopyOption; ++import java.util.HashMap; ++import java.util.Locale; ++import java.util.Map; + import java.util.Set; + import java.util.jar.Manifest; + + import org.apache.catalina.LifecycleException; + import org.apache.catalina.WebResource; ++import org.apache.catalina.WebResourceLockSet; + import org.apache.catalina.WebResourceRoot; + import org.apache.catalina.WebResourceRoot.ResourceSetType; + import org.apache.catalina.util.ResourceSet; + import org.apache.juli.logging.Log; + import org.apache.juli.logging.LogFactory; ++import org.apache.tomcat.util.http.RequestUtil; + + /** + * Represents a {@link org.apache.catalina.WebResourceSet} based on a directory. + */ +-public class DirResourceSet extends AbstractFileResourceSet { ++public class DirResourceSet extends AbstractFileResourceSet implements WebResourceLockSet { + + private static final Log log = LogFactory.getLog(DirResourceSet.class); + ++ private boolean caseSensitive = true; ++ ++ private Map resourceLocksByPath = new HashMap<>(); ++ private Object resourceLocksByPathLock = new Object(); ++ ++ + /** + * A no argument constructor is required for this to work with the digester. + */ +@@ -91,22 +102,33 @@ public WebResource getResource(String path) { + String webAppMount = getWebAppMount(); + WebResourceRoot root = getRoot(); + if (path.startsWith(webAppMount)) { +- File f = file(path.substring(webAppMount.length()), false); +- if (f == null) { +- return new EmptyResource(root, path); +- } +- if (!f.exists()) { +- return new EmptyResource(root, path, f); +- } +- if (f.isDirectory() && path.charAt(path.length() - 1) != '/') { +- path = path + '/'; ++ /* ++ * Lock the path for reading until the WebResource has been constructed. The lock prevents concurrent reads ++ * and writes (e.g. HTTP GET and PUT / DELETE) for the same path causing corruption of the FileResource ++ * where some of the fields are set as if the file exists and some as set as if it does not. ++ */ ++ ResourceLock lock = lockForRead(path); ++ try { ++ File f = file(path.substring(webAppMount.length()), false); ++ if (f == null) { ++ return new EmptyResource(root, path); ++ } ++ if (!f.exists()) { ++ return new EmptyResource(root, path, f); ++ } ++ if (f.isDirectory() && path.charAt(path.length() - 1) != '/') { ++ path = path + '/'; ++ } ++ return new FileResource(root, path, f, isReadOnly(), getManifest(), this, lock.key); ++ } finally { ++ unlockForRead(lock); + } +- return new FileResource(root, path, f, isReadOnly(), getManifest()); + } else { + return new EmptyResource(root, path); + } + } + ++ + @Override + public String[] list(String path) { + checkPath(path); +@@ -246,32 +268,42 @@ public boolean write(String path, InputStream is, boolean overwrite) { + return false; + } + +- File dest = null; + String webAppMount = getWebAppMount(); +- if (path.startsWith(webAppMount)) { ++ if (!path.startsWith(webAppMount)) { ++ return false; ++ } ++ ++ File dest = null; ++ /* ++ * Lock the path for writing until the write is complete. The lock prevents concurrent reads and writes (e.g. ++ * HTTP GET and PUT / DELETE) for the same path causing corruption of the FileResource where some of the fields ++ * are set as if the file exists and some as set as if it does not. ++ */ ++ ResourceLock lock = lockForWrite(path); ++ try { + dest = file(path.substring(webAppMount.length()), false); + if (dest == null) { + return false; + } +- } else { +- return false; +- } + +- if (dest.exists() && !overwrite) { +- return false; +- } ++ if (dest.exists() && !overwrite) { ++ return false; ++ } + +- try { +- if (overwrite) { +- Files.copy(is, dest.toPath(), StandardCopyOption.REPLACE_EXISTING); +- } else { +- Files.copy(is, dest.toPath()); ++ try { ++ if (overwrite) { ++ Files.copy(is, dest.toPath(), StandardCopyOption.REPLACE_EXISTING); ++ } else { ++ Files.copy(is, dest.toPath()); ++ } ++ } catch (IOException ioe) { ++ return false; + } +- } catch (IOException ioe) { +- return false; +- } + +- return true; ++ return true; ++ } finally { ++ unlockForWrite(lock); ++ } + } + + @Override +@@ -286,6 +318,7 @@ protected void checkType(File file) { + @Override + protected void initInternal() throws LifecycleException { + super.initInternal(); ++ caseSensitive = isCaseSensitive(); + // Is this an exploded web application? + if (getWebAppMount().equals("")) { + // Look for a manifest +@@ -299,4 +332,114 @@ protected void initInternal() throws LifecycleException { + } + } + } ++ ++ ++ /* ++ * Determines if this ResourceSet is based on a case sensitive file system or not. ++ */ ++ private boolean isCaseSensitive() { ++ try { ++ String canonicalPath = getFileBase().getCanonicalPath(); ++ File upper = new File(canonicalPath.toUpperCase(Locale.ENGLISH)); ++ if (!canonicalPath.equals(upper.getCanonicalPath())) { ++ return true; ++ } ++ File lower = new File(canonicalPath.toLowerCase(Locale.ENGLISH)); ++ if (!canonicalPath.equals(lower.getCanonicalPath())) { ++ return true; ++ } ++ /* ++ * Both upper and lower case versions of the current fileBase have the same canonical path so the file ++ * system must be case insensitive. ++ */ ++ } catch (IOException ioe) { ++ log.warn(sm.getString("dirResourceSet.isCaseSensitive.fail", getFileBase().getAbsolutePath()), ioe); ++ } ++ ++ return false; ++ } ++ ++ ++ private String getLockKey(String path) { ++ // Normalize path to ensure that the same key is used for the same path. ++ String normalisedPath = RequestUtil.normalize(path); ++ if (caseSensitive) { ++ return normalisedPath; ++ } ++ return normalisedPath.toLowerCase(Locale.ENGLISH); ++ } ++ ++ ++ @Override ++ public ResourceLock lockForRead(String path) { ++ String key = getLockKey(path); ++ ResourceLock resourceLock = null; ++ synchronized (resourceLocksByPathLock) { ++ /* ++ * Obtain the ResourceLock and increment the usage count inside the sync to ensure that that map always has ++ * a consistent view of the currently "in-use" ResourceLocks. ++ */ ++ resourceLock = resourceLocksByPath.get(key); ++ if (resourceLock == null) { ++ resourceLock = new ResourceLock(key); ++ } ++ resourceLock.count.incrementAndGet(); ++ } ++ // Obtain the lock outside the sync as it will block if there is a current write lock. ++ resourceLock.reentrantLock.readLock().lock(); ++ return resourceLock; ++ } ++ ++ ++ @Override ++ public void unlockForRead(ResourceLock resourceLock) { ++ // Unlock outside the sync as there is no need to do it inside. ++ resourceLock.reentrantLock.readLock().unlock(); ++ synchronized (resourceLocksByPathLock) { ++ /* ++ * Decrement the usage count and remove ResourceLocks no longer required inside the sync to ensure that that ++ * map always has a consistent view of the currently "in-use" ResourceLocks. ++ */ ++ if (resourceLock.count.decrementAndGet() == 0) { ++ resourceLocksByPath.remove(resourceLock.key); ++ } ++ } ++ } ++ ++ ++ @Override ++ public ResourceLock lockForWrite(String path) { ++ String key = getLockKey(path); ++ ResourceLock resourceLock = null; ++ synchronized (resourceLocksByPathLock) { ++ /* ++ * Obtain the ResourceLock and increment the usage count inside the sync to ensure that that map always has ++ * a consistent view of the currently "in-use" ResourceLocks. ++ */ ++ resourceLock = resourceLocksByPath.get(key); ++ if (resourceLock == null) { ++ resourceLock = new ResourceLock(key); ++ } ++ resourceLock.count.incrementAndGet(); ++ } ++ // Obtain the lock outside the sync as it will block if there are any other current locks. ++ resourceLock.reentrantLock.writeLock().lock(); ++ return resourceLock; ++ } ++ ++ ++ @Override ++ public void unlockForWrite(ResourceLock resourceLock) { ++ // Unlock outside the sync as there is no need to do it inside. ++ resourceLock.reentrantLock.writeLock().unlock(); ++ synchronized (resourceLocksByPathLock) { ++ /* ++ * Decrement the usage count and remove ResourceLocks no longer required inside the sync to ensure that that ++ * map always has a consistent view of the currently "in-use" ResourceLocks. ++ */ ++ if (resourceLock.count.decrementAndGet() == 0) { ++ resourceLocksByPath.remove(resourceLock.key); ++ } ++ } ++ } + } +diff --git a/java/org/apache/catalina/webresources/FileResource.java b/java/org/apache/catalina/webresources/FileResource.java +index 32ce5bfa62c3..354022f9096d 100644 +--- a/java/org/apache/catalina/webresources/FileResource.java ++++ b/java/org/apache/catalina/webresources/FileResource.java +@@ -31,6 +31,8 @@ + import java.security.cert.Certificate; + import java.util.jar.Manifest; + ++import org.apache.catalina.WebResourceLockSet; ++import org.apache.catalina.WebResourceLockSet.ResourceLock; + import org.apache.catalina.WebResourceRoot; + import org.apache.juli.logging.Log; + import org.apache.juli.logging.LogFactory; +@@ -62,10 +64,20 @@ public class FileResource extends AbstractResource { + private final boolean readOnly; + private final Manifest manifest; + private final boolean needConvert; ++ private final WebResourceLockSet lockSet; ++ private final String lockKey; + + public FileResource(WebResourceRoot root, String webAppPath, File resource, boolean readOnly, Manifest manifest) { ++ this(root, webAppPath, resource, readOnly, manifest, null, null); ++ } ++ ++ ++ public FileResource(WebResourceRoot root, String webAppPath, File resource, boolean readOnly, Manifest manifest, ++ WebResourceLockSet lockSet, String lockKey) { + super(root, webAppPath); + this.resource = resource; ++ this.lockSet = lockSet; ++ this.lockKey = lockKey; + + if (webAppPath.charAt(webAppPath.length() - 1) == '/') { + String realName = resource.getName() + '/'; +@@ -117,7 +129,22 @@ public boolean delete() { + if (readOnly) { + return false; + } +- return resource.delete(); ++ /* ++ * Lock the path for writing until the delete is complete. The lock prevents concurrent reads and writes (e.g. ++ * HTTP GET and PUT / DELETE) for the same path causing corruption of the FileResource where some of the fields ++ * are set as if the file exists and some as set as if it does not. ++ */ ++ ResourceLock lock = null; ++ if (lockSet != null) { ++ lock = lockSet.lockForWrite(lockKey); ++ } ++ try { ++ return resource.delete(); ++ } finally { ++ if (lockSet != null) { ++ lockSet.unlockForWrite(lock); ++ } ++ } + } + + @Override +diff --git a/java/org/apache/catalina/webresources/LocalStrings.properties b/java/org/apache/catalina/webresources/LocalStrings.properties +index 67d76d3b3b32..301c13eb8063 100644 +--- a/java/org/apache/catalina/webresources/LocalStrings.properties ++++ b/java/org/apache/catalina/webresources/LocalStrings.properties +@@ -36,6 +36,7 @@ cachedResource.invalidURL=Unable to create an instance of CachedResourceURLStrea + + classpathUrlStreamHandler.notFound=Unable to load the resource [{0}] using the thread context class loader or the current class''s class loader + ++dirResourceSet.isCaseSensitive.fail=Error trying to determine if file system at [{0}] is case sensitive so assuming it is not case sensitive + dirResourceSet.manifestFail=Failed to read manifest from [{0}] + dirResourceSet.notDirectory=The directory specified by base and internal path [{0}]{1}[{2}] does not exist. + dirResourceSet.writeNpe=The input stream may not be null diff --git a/CVE-2024-50379-2.patch b/CVE-2024-50379-2.patch new file mode 100644 index 0000000..8bbcace --- /dev/null +++ b/CVE-2024-50379-2.patch @@ -0,0 +1,32 @@ +From 631500b0c9b2a2a2abb707e3de2e10a5936e5d41 Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Fri, 15 Nov 2024 15:55:37 +0000 +Subject: [PATCH] Fix for inconsistent metadata was incomplete + +Origin: https://github.com/apache/tomcat/commit/631500b0c9b2a2a2abb707e3de2e10a5936e5d41 +Need to add key to map once created so it is visible to other threads +--- + java/org/apache/catalina/webresources/DirResourceSet.java | 2 ++ + webapps/docs/changelog.xml | 4 ++++ + 2 files changed, 6 insertions(+) + +diff --git a/java/org/apache/catalina/webresources/DirResourceSet.java b/java/org/apache/catalina/webresources/DirResourceSet.java +index 02ddc6ec887c..f1d4e86199ee 100644 +--- a/java/org/apache/catalina/webresources/DirResourceSet.java ++++ b/java/org/apache/catalina/webresources/DirResourceSet.java +@@ -382,6 +382,7 @@ public ResourceLock lockForRead(String path) { + resourceLock = resourceLocksByPath.get(key); + if (resourceLock == null) { + resourceLock = new ResourceLock(key); ++ resourceLocksByPath.put(key, resourceLock); + } + resourceLock.count.incrementAndGet(); + } +@@ -419,6 +420,7 @@ public ResourceLock lockForWrite(String path) { + resourceLock = resourceLocksByPath.get(key); + if (resourceLock == null) { + resourceLock = new ResourceLock(key); ++ resourceLocksByPath.put(key, resourceLock); + } + resourceLock.count.incrementAndGet(); + } diff --git a/CVE-2024-54677-1.patch b/CVE-2024-54677-1.patch new file mode 100644 index 0000000..10e3dd3 --- /dev/null +++ b/CVE-2024-54677-1.patch @@ -0,0 +1,48 @@ +From 1d88dd3ffaed76188dd4ee32ce77709ce6e153cd Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Mon, 2 Dec 2024 16:36:31 +0000 +Subject: [PATCH] Obfuscate session cookie values for JSON output as well as + HTML + +Origin: https://github.com/apache/tomcat/commit/1d88dd3ffaed76188dd4ee32ce77709ce6e153cd +--- + webapps/docs/changelog.xml | 4 ++++ + .../WEB-INF/classes/RequestHeaderExample.java | 18 +++++++++++++++--- + 2 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/webapps/examples/WEB-INF/classes/RequestHeaderExample.java b/webapps/examples/WEB-INF/classes/RequestHeaderExample.java +index b01c84f33e48..e32f8c233674 100644 +--- a/webapps/examples/WEB-INF/classes/RequestHeaderExample.java ++++ b/webapps/examples/WEB-INF/classes/RequestHeaderExample.java +@@ -73,7 +73,7 @@ protected boolean prefersJSON(String acceptHeader) { + + // text/html, application/html, etc. + if (accept.contains("html")) { +- return false; ++ return true; + } + } + return false; +@@ -138,8 +138,20 @@ protected void renderJSON(HttpServletRequest request, HttpServletResponse respon + String headerName = e.nextElement(); + String headerValue = request.getHeader(headerName); + +- out.append("{\"").append(JSONFilter.escape(headerName)).append("\":\"") +- .append(JSONFilter.escape(headerValue)).append("\"}"); ++ out.append("{\"").append(JSONFilter.escape(headerName)).append("\":\""); ++ ++ ++ if (headerName.toLowerCase(Locale.ENGLISH).contains("cookie")) { ++ HttpSession session = request.getSession(false); ++ String sessionId = null; ++ if (session != null) { ++ sessionId = session.getId(); ++ } ++ out.append(JSONFilter.escape(CookieFilter.filter(headerValue, sessionId))); ++ } else { ++ out.append(JSONFilter.escape(headerValue)); ++ } ++ out.append("\"}"); + + if (e.hasMoreElements()) { + out.append(','); diff --git a/CVE-2024-54677-2.patch b/CVE-2024-54677-2.patch new file mode 100644 index 0000000..425a19f --- /dev/null +++ b/CVE-2024-54677-2.patch @@ -0,0 +1,61 @@ +From 721544ea28e92549824b106be954a9f411867a1c Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Mon, 2 Dec 2024 17:39:05 +0000 +Subject: [PATCH] Add the ability to delete session attributes. + +Origin: https://github.com/apache/tomcat/commit/721544ea28e92549824b106be954a9f411867a1c +--- + webapps/docs/changelog.xml | 4 ++++ + .../examples/WEB-INF/classes/SessionExample.java | 14 +++++++++++--- + 2 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/webapps/examples/WEB-INF/classes/SessionExample.java b/webapps/examples/WEB-INF/classes/SessionExample.java +index 407e2b3c0b0f..b3de2f866956 100644 +--- a/webapps/examples/WEB-INF/classes/SessionExample.java ++++ b/webapps/examples/WEB-INF/classes/SessionExample.java +@@ -1,3 +1,4 @@ ++ + /* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with +@@ -16,6 +17,8 @@ + + import java.io.IOException; + import java.io.PrintWriter; ++import java.net.URLEncoder; ++import java.nio.charset.StandardCharsets; + import java.util.Date; + import java.util.Enumeration; + import java.util.ResourceBundle; +@@ -75,7 +78,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro + + String dataName = request.getParameter("dataname"); + String dataValue = request.getParameter("datavalue"); +- if (dataName != null && dataValue != null) { ++ if (dataName != null) { + session.setAttribute(dataName, dataValue); + } + +@@ -85,7 +88,12 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro + while (names.hasMoreElements()) { + String name = names.nextElement(); + String value = session.getAttribute(name).toString(); +- out.println(HTMLFilter.filter(name) + " = " + HTMLFilter.filter(value) + "
"); ++ out.println(HTMLFilter.filter(name) + " = " + HTMLFilter.filter(value)); ++ out.print("delete"); ++ out.println("
"); + } + + out.println("

"); +@@ -117,7 +125,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro + out.println(""); + + out.print("

URL encoded "); + + out.println(""); diff --git a/CVE-2024-54677-3.patch b/CVE-2024-54677-3.patch new file mode 100644 index 0000000..9b90341 --- /dev/null +++ b/CVE-2024-54677-3.patch @@ -0,0 +1,137 @@ +From 84065e26ca4555e63a922bb29b13b0a1c86b7654 Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Mon, 2 Dec 2024 18:09:44 +0000 +Subject: [PATCH] Add a limit of 10 attributes per session to the session + example + +Origin: https://github.com/apache/tomcat/commit/84065e26ca4555e63a922bb29b13b0a1c86b7654 +--- + webapps/docs/changelog.xml | 4 + + .../WEB-INF/classes/SessionExample.java | 94 ++++++++++++------- + 2 files changed, 64 insertions(+), 34 deletions(-) + +diff --git a/webapps/examples/WEB-INF/classes/SessionExample.java b/webapps/examples/WEB-INF/classes/SessionExample.java +index b3de2f866956..60eaa2e03e4b 100644 +--- a/webapps/examples/WEB-INF/classes/SessionExample.java ++++ b/webapps/examples/WEB-INF/classes/SessionExample.java +@@ -41,6 +41,9 @@ public class SessionExample extends HttpServlet { + + private static final long serialVersionUID = 1L; + ++ private static final int SESSION_ATTRIBUTE_COUNT_LIMIT = 10; ++ ++ + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + ResourceBundle rb = ResourceBundle.getBundle("LocalStrings", request.getLocale()); +@@ -76,15 +79,34 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro + out.println(rb.getString("sessions.lastaccessed") + " "); + out.println(new Date(session.getLastAccessedTime())); + ++ // Count the existing attributes ++ int sessionAttributeCount = 0; ++ Enumeration names = session.getAttributeNames(); ++ while (names.hasMoreElements()) { ++ names.nextElement(); ++ sessionAttributeCount++; ++ } ++ + String dataName = request.getParameter("dataname"); + String dataValue = request.getParameter("datavalue"); + if (dataName != null) { +- session.setAttribute(dataName, dataValue); ++ if (dataValue == null) { ++ session.removeAttribute(dataName); ++ sessionAttributeCount--; ++ } else if (sessionAttributeCount < SESSION_ATTRIBUTE_COUNT_LIMIT) { ++ session.setAttribute(dataName, dataValue); ++ sessionAttributeCount++; ++ } else { ++ out.print("

Session attribute ["); ++ out.print(HTMLFilter.filter(dataName)); ++ out.print("] not added as there are already "+ SESSION_ATTRIBUTE_COUNT_LIMIT + " attributes in the "); ++ out.println("session. Delete an attribute before adding another."); ++ } + } + +- out.println("

"); ++ out.println("

"); + out.println(rb.getString("sessions.data") + "
"); +- Enumeration names = session.getAttributeNames(); ++ names = session.getAttributeNames(); + while (names.hasMoreElements()) { + String name = names.nextElement(); + String value = session.getAttribute(name).toString(); +@@ -96,37 +118,41 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro + out.println("
"); + } + +- out.println("

"); +- out.print("

"); +- out.println(rb.getString("sessions.dataname")); +- out.println(""); +- out.println("
"); +- out.println(rb.getString("sessions.datavalue")); +- out.println(""); +- out.println("
"); +- out.println(""); +- out.println("
"); +- +- out.println("

GET based form:
"); +- out.print("

"); +- out.println(rb.getString("sessions.dataname")); +- out.println(""); +- out.println("
"); +- out.println(rb.getString("sessions.datavalue")); +- out.println(""); +- out.println("
"); +- out.println(""); +- out.println("
"); +- +- out.print("

URL encoded "); ++ if (sessionAttributeCount < SESSION_ATTRIBUTE_COUNT_LIMIT) { ++ out.println("

"); ++ out.print("

"); ++ out.println(rb.getString("sessions.dataname")); ++ out.println(""); ++ out.println("
"); ++ out.println(rb.getString("sessions.datavalue")); ++ out.println(""); ++ out.println("
"); ++ out.println(""); ++ out.println("
"); ++ ++ out.println("

GET based form:
"); ++ out.print("

"); ++ out.println(rb.getString("sessions.dataname")); ++ out.println(""); ++ out.println("
"); ++ out.println(rb.getString("sessions.datavalue")); ++ out.println(""); ++ out.println("
"); ++ out.println(""); ++ out.println("
"); ++ ++ out.print("

URL encoded "); ++ } else { ++ out.print("

You may not add more than " + SESSION_ATTRIBUTE_COUNT_LIMIT + " attributes to this session."); ++ } + + out.println(""); + out.println(""); diff --git a/CVE-2024-54677-4.patch b/CVE-2024-54677-4.patch new file mode 100644 index 0000000..a975cd2 --- /dev/null +++ b/CVE-2024-54677-4.patch @@ -0,0 +1,31 @@ +From 3315a9027a7eaab18f42625b97b569940ff1365d Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Mon, 2 Dec 2024 18:13:07 +0000 +Subject: [PATCH] Fix backprot + +Origin: https://github.com/apache/tomcat/commit/3315a9027a7eaab18f42625b97b569940ff1365d +--- + webapps/examples/WEB-INF/classes/SessionExample.java | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/webapps/examples/WEB-INF/classes/SessionExample.java b/webapps/examples/WEB-INF/classes/SessionExample.java +index 60eaa2e03e4b..14e7c9701c84 100644 +--- a/webapps/examples/WEB-INF/classes/SessionExample.java ++++ b/webapps/examples/WEB-INF/classes/SessionExample.java +@@ -18,7 +18,6 @@ + import java.io.IOException; + import java.io.PrintWriter; + import java.net.URLEncoder; +-import java.nio.charset.StandardCharsets; + import java.util.Date; + import java.util.Enumeration; + import java.util.ResourceBundle; +@@ -113,7 +112,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro + out.println(HTMLFilter.filter(name) + " = " + HTMLFilter.filter(value)); + out.print("delete"); + out.println("
"); + } diff --git a/CVE-2024-54677-5.patch b/CVE-2024-54677-5.patch new file mode 100644 index 0000000..2d4aa0b --- /dev/null +++ b/CVE-2024-54677-5.patch @@ -0,0 +1,97 @@ +From c2f7ce21c3fb12caefee87c517a8bb4f80700044 Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Tue, 3 Dec 2024 17:45:03 +0000 +Subject: [PATCH] Limit to 10 attributes. Add option to delete attribute. + +Origin: https://github.com/apache/tomcat/commit/c2f7ce21c3fb12caefee87c517a8bb4f80700044 +--- + webapps/docs/changelog.xml | 5 ++ + .../examples/jsp/security/protected/index.jsp | 49 ++++++++++++++++--- + 2 files changed, 46 insertions(+), 8 deletions(-) + +diff --git a/webapps/examples/jsp/security/protected/index.jsp b/webapps/examples/jsp/security/protected/index.jsp +index 09c23e721910..987a30fd1878 100644 +--- a/webapps/examples/jsp/security/protected/index.jsp ++++ b/webapps/examples/jsp/security/protected/index.jsp +@@ -14,8 +14,10 @@ + See the License for the specific language governing permissions and + limitations under the License. + --%> +-<%@ page import="java.util.Enumeration" %> ++<%@ page import="java.net.URLEncoder" %> ++<%@ page import="java.nio.charset.StandardCharsets" %> + <%@ page import="java.security.Principal" %> ++<%@ page import="java.util.Enumeration" %> + <%@ page import="org.apache.catalina.TomcatPrincipal" %> + <% + if (request.getParameter("logoff") != null) { +@@ -121,31 +123,62 @@ enter it here: + %> +

+ ++<% ++ // Count the existing attributes ++ int sessionAttributeCount = 0; ++ Enumeration names = session.getAttributeNames(); ++ while (names.hasMoreElements()) { ++ names.nextElement(); ++ sessionAttributeCount++; ++ } ++ ++ String dataName = request.getParameter("dataName"); ++ String dataValue = request.getParameter("dataValue"); ++ if (dataName != null) { ++ if (dataValue == null) { ++ session.removeAttribute(dataName); ++ sessionAttributeCount--; ++ } else if (sessionAttributeCount < 10) { ++ session.setAttribute(dataName, dataValue); ++ sessionAttributeCount++; ++ } else { ++%> ++

Session attribute [<%= util.HTMLFilter.filter(dataName) %>] not added as there are already 10 attributes in the ++session. Delete an attribute before adding another.

++<% ++ } ++ } ++ ++ if (sessionAttributeCount < 10) { ++%> + To add some data to the authenticated session, enter it here: +
+ + + +
+-

+- + <% +- String dataName = request.getParameter("dataName"); +- if (dataName != null) { +- session.setAttribute(dataName, request.getParameter("dataValue")); ++ } else { ++%> ++

You may not add more than 10 attributes to this session.

++<% + } + %> ++

++ +

The authenticated session contains the following attributes:

+ + + <% +- Enumeration names = session.getAttributeNames(); ++ names = session.getAttributeNames(); + while (names.hasMoreElements()) { + String name = names.nextElement(); ++ String value = session.getAttribute(name).toString(); + %> + + +- ++ ++ + + <% + } diff --git a/CVE-2024-54677-6.patch b/CVE-2024-54677-6.patch new file mode 100644 index 0000000..ca0eeae --- /dev/null +++ b/CVE-2024-54677-6.patch @@ -0,0 +1,23 @@ +From 75ff7e8622edcc024b268677aa789ee8f0880ecc Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Wed, 4 Dec 2024 07:27:40 +0000 +Subject: [PATCH] Fix back-port + +Origin: https://github.com/apache/tomcat/commit/75ff7e8622edcc024b268677aa789ee8f0880ecc +--- + webapps/examples/jsp/security/protected/index.jsp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/webapps/examples/jsp/security/protected/index.jsp b/webapps/examples/jsp/security/protected/index.jsp +index 987a30fd1878..f4c90b8b715c 100644 +--- a/webapps/examples/jsp/security/protected/index.jsp ++++ b/webapps/examples/jsp/security/protected/index.jsp +@@ -178,7 +178,7 @@ To add some data to the authenticated session, enter it here: + + + +- ++ + + <% + } diff --git a/CVE-2024-54677-7.patch b/CVE-2024-54677-7.patch new file mode 100644 index 0000000..199e4c0 --- /dev/null +++ b/CVE-2024-54677-7.patch @@ -0,0 +1,270 @@ +From 4d5cc6538d91386f950373ac8120e98c2c78ed3a Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Wed, 4 Dec 2024 15:14:17 +0000 +Subject: [PATCH] Limit shopping cart to pre-defined items + +Origin: https://github.com/apache/tomcat/commit/4d5cc6538d91386f950373ac8120e98c2c78ed3a +--- + webapps/docs/changelog.xml | 4 ++ + .../WEB-INF/classes/sessions/DummyCart.java | 42 +++++++++++-------- + .../WEB-INF/classes/sessions/Item.java | 37 ++++++++++++++++ + webapps/examples/jsp/index.html | 2 +- + webapps/examples/jsp/sessions/carts.jsp | 8 ++-- + webapps/examples/jsp/sessions/crt.html | 7 +++- + .../jsp/sessions/{carts.html => shopping.jsp} | 41 +++++++++--------- + 7 files changed, 95 insertions(+), 46 deletions(-) + create mode 100644 webapps/examples/WEB-INF/classes/sessions/Item.java + rename webapps/examples/jsp/sessions/{carts.html => shopping.jsp} (75%) + +diff --git a/webapps/examples/WEB-INF/classes/sessions/DummyCart.java b/webapps/examples/WEB-INF/classes/sessions/DummyCart.java +index 44decc98a9a2..7088557b9595 100644 +--- a/webapps/examples/WEB-INF/classes/sessions/DummyCart.java ++++ b/webapps/examples/WEB-INF/classes/sessions/DummyCart.java +@@ -16,42 +16,50 @@ + */ + package sessions; + +-import java.util.ArrayList; + import java.util.Collections; +-import java.util.List; ++import java.util.HashSet; ++import java.util.Set; + + public class DummyCart { +- final List items = Collections.synchronizedList(new ArrayList<>()); ++ final Set items = Collections.synchronizedSet(new HashSet<>()); ++ int itemId = -1; + String submit = null; +- String item = null; + +- private void addItem(String name) { +- items.add(name); ++ public void setItemId(int itemId) { ++ this.itemId = itemId; + } + +- private void removeItem(String name) { +- items.remove(name); ++ public void setSubmit(String s) { ++ submit = s; + } + +- public void setItem(String name) { +- item = name; ++ private void addItem(int itemId) { ++ try { ++ items.add(Item.values()[itemId]); ++ } catch (ArrayIndexOutOfBoundsException e) { ++ // Ignore. Can only happen if user edits URL directly. ++ } + } + +- public void setSubmit(String s) { +- submit = s; ++ private void removeItem(int itemId) { ++ try { ++ items.remove(Item.values()[itemId]); ++ } catch (ArrayIndexOutOfBoundsException e) { ++ // Ignore. Can only happen if user edits URL directly. ++ } + } + +- public String[] getItems() { +- return items.toArray(new String[0]); ++ public Item[] getItems() { ++ return items.toArray(new Item[0]); + } + + public void processRequest() { + // null value for submit - user hit enter instead of clicking on + // "add" or "remove" + if (submit == null || submit.equals("add")) { +- addItem(item); ++ addItem(itemId); + } else if (submit.equals("remove")) { +- removeItem(item); ++ removeItem(itemId); + } + + // reset at the end of the request +@@ -61,6 +69,6 @@ public void processRequest() { + // reset + private void reset() { + submit = null; +- item = null; ++ itemId = -1; + } + } +diff --git a/webapps/examples/WEB-INF/classes/sessions/Item.java b/webapps/examples/WEB-INF/classes/sessions/Item.java +new file mode 100644 +index 000000000000..447d04443744 +--- /dev/null ++++ b/webapps/examples/WEB-INF/classes/sessions/Item.java +@@ -0,0 +1,37 @@ ++/* ++ * 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 sessions; ++ ++public enum Item { ++ ++ VIDEO("Beavis & Butt-head Video collection"), ++ MOVIE("X-files movie"), ++ TAPES("Twin peaks tapes"), ++ CD("NIN CD"), ++ BOOK("JSP Book"), ++ TICKETS("Concert tickets"); ++ ++ private final String title; ++ ++ Item(String title) { ++ this.title = title; ++ } ++ ++ public String getTitle() { ++ return title; ++ } ++} +diff --git a/webapps/examples/jsp/index.html b/webapps/examples/jsp/index.html +index b2371207cfe7..dc25005b2710 100644 +--- a/webapps/examples/jsp/index.html ++++ b/webapps/examples/jsp/index.html +@@ -228,7 +228,7 @@

JSP 1.2 Examples

+
+ + +- ++ + + + +diff --git a/webapps/examples/jsp/sessions/carts.jsp b/webapps/examples/jsp/sessions/carts.jsp +index dc51495c4bec..fa5624dee6bd 100644 +--- a/webapps/examples/jsp/sessions/carts.jsp ++++ b/webapps/examples/jsp/sessions/carts.jsp +@@ -27,10 +27,10 @@ +
You have the following items in your cart: +
    + <% +- String[] items = cart.getItems(); +- for (String item : items) { ++ Item[] items = cart.getItems(); ++ for (Item item : items) { + %> +-
  1. <% out.print(util.HTMLFilter.filter(item)); %> ++
  2. <% out.print(util.HTMLFilter.filter(item.getTitle())); %> + <% + } + %> +@@ -39,5 +39,5 @@ + + +
    +-<%@ include file ="carts.html" %> ++<%@ include file ="shopping.jsp" %> + +diff --git a/webapps/examples/jsp/sessions/crt.html b/webapps/examples/jsp/sessions/crt.html +index 11e6edafe0e9..28ace66012c7 100644 +--- a/webapps/examples/jsp/sessions/crt.html ++++ b/webapps/examples/jsp/sessions/crt.html +@@ -22,9 +22,12 @@ + + + +-

    ++

    + +-

    Source Code for Cart Example ++

    Source Code for Cart Example Shopping Page ++

    ++ ++

    Source Code for Cart Example Cart Page +

    + +

    Property Sheet for DummyCart +diff --git a/webapps/examples/jsp/sessions/carts.html b/webapps/examples/jsp/sessions/shopping.jsp +similarity index 75% +rename from webapps/examples/jsp/sessions/carts.html +rename to webapps/examples/jsp/sessions/shopping.jsp +index 834ee0a594fd..3487b1029547 100644 +--- a/webapps/examples/jsp/sessions/carts.html ++++ b/webapps/examples/jsp/sessions/shopping.jsp +@@ -1,5 +1,4 @@ +- +- +- ++--%> ++<%@ page import="sessions.Item" %> ++ + +- carts ++Shopping Cart Example + + +- ++ + + +
    +-
    ++
    + Please enter item to add or remove: +
    +-Add Item: +- +- +- ++Select Item: ++ ++ + +

    + +@@ -48,6 +45,6 @@ + + + +-
    ++
    + + diff --git a/CVE-2024-54677-8.patch b/CVE-2024-54677-8.patch new file mode 100644 index 0000000..e4e617e --- /dev/null +++ b/CVE-2024-54677-8.patch @@ -0,0 +1,717 @@ +From 84c4af76e7a10fc7f8630ce62e6a46632ea4a90e Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Wed, 4 Dec 2024 18:41:34 +0000 +Subject: [PATCH] Remove JSP calendar example. + +Origin: https://github.com/apache/tomcat/commit/84c4af76e7a10fc7f8630ce62e6a46632ea4a90e +--- + build.xml | 9 -- + webapps/docs/changelog.xml | 3 + + .../examples/WEB-INF/classes/cal/Entries.java | 63 -------- + .../examples/WEB-INF/classes/cal/Entry.java | 52 ------ + .../WEB-INF/classes/cal/JspCalendar.java | 152 ------------------ + .../WEB-INF/classes/cal/TableBean.java | 106 ------------ + webapps/examples/jsp/cal/cal1.jsp | 94 ----------- + webapps/examples/jsp/cal/cal2.jsp | 45 ------ + webapps/examples/jsp/cal/calendar.html | 43 ----- + webapps/examples/jsp/cal/login.html | 47 ------ + webapps/examples/jsp/index.html | 8 - + 11 files changed, 3 insertions(+), 619 deletions(-) + delete mode 100644 webapps/examples/WEB-INF/classes/cal/Entries.java + delete mode 100644 webapps/examples/WEB-INF/classes/cal/Entry.java + delete mode 100644 webapps/examples/WEB-INF/classes/cal/JspCalendar.java + delete mode 100644 webapps/examples/WEB-INF/classes/cal/TableBean.java + delete mode 100644 webapps/examples/jsp/cal/cal1.jsp + delete mode 100644 webapps/examples/jsp/cal/cal2.jsp + delete mode 100644 webapps/examples/jsp/cal/calendar.html + delete mode 100644 webapps/examples/jsp/cal/login.html + +diff --git a/build.xml b/build.xml +index 52f5fa11252f..5b3e1738c283 100644 +--- a/build.xml ++++ b/build.xml +@@ -1646,15 +1646,6 @@ + + + +- +- +- +- +- +- +- +- +- + + + +diff --git a/webapps/examples/WEB-INF/classes/cal/Entries.java b/webapps/examples/WEB-INF/classes/cal/Entries.java +deleted file mode 100644 +index cac611a03b1f..000000000000 +--- a/webapps/examples/WEB-INF/classes/cal/Entries.java ++++ /dev/null +@@ -1,63 +0,0 @@ +-/* +- * 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 cal; +- +-import java.util.Map; +-import java.util.concurrent.ConcurrentHashMap; +- +-import javax.servlet.http.HttpServletRequest; +- +-public class Entries { +- +- private final Map entries; +- private static final String[] time = { "8am", "9am", "10am", "11am", +- "12pm", "1pm", "2pm", "3pm", "4pm", "5pm", "6pm", "7pm", "8pm" }; +- public static final int rows = 12; +- +- public Entries() { +- entries = new ConcurrentHashMap<>(rows); +- for (int i = 0; i < rows; i++) { +- entries.put(time[i], new Entry(time[i])); +- } +- } +- +- public int getRows() { +- return rows; +- } +- +- public Entry getEntry(int index) { +- return this.entries.get(time[index]); +- } +- +- public int getIndex(String tm) { +- for (int i = 0; i < rows; i++) { +- if (tm.equals(time[i])) { +- return i; +- } +- } +- return -1; +- } +- +- public void processRequest(HttpServletRequest request, String tm) { +- int index = getIndex(tm); +- if (index >= 0) { +- String descr = request.getParameter("description"); +- entries.get(time[index]).setDescription(descr); +- } +- } +- +-} +diff --git a/webapps/examples/WEB-INF/classes/cal/Entry.java b/webapps/examples/WEB-INF/classes/cal/Entry.java +deleted file mode 100644 +index ac248bfa3169..000000000000 +--- a/webapps/examples/WEB-INF/classes/cal/Entry.java ++++ /dev/null +@@ -1,52 +0,0 @@ +-/* +- * 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 cal; +- +-public class Entry { +- +- final String hour; +- String description; +- +- public Entry(String hour) { +- this.hour = hour; +- this.description = ""; +- +- } +- +- public String getHour() { +- return this.hour; +- } +- +- public String getColor() { +- if (description.equals("")) { +- return "lightblue"; +- } +- return "red"; +- } +- +- public String getDescription() { +- if (description.equals("")) { +- return "None"; +- } +- return this.description; +- } +- +- public void setDescription(String descr) { +- description = descr; +- } +- +-} +diff --git a/webapps/examples/WEB-INF/classes/cal/JspCalendar.java b/webapps/examples/WEB-INF/classes/cal/JspCalendar.java +deleted file mode 100644 +index 29541cccb400..000000000000 +--- a/webapps/examples/WEB-INF/classes/cal/JspCalendar.java ++++ /dev/null +@@ -1,152 +0,0 @@ +-/* +- * 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 cal; +- +-import java.util.Calendar; +-import java.util.Date; +- +-public class JspCalendar { +- final Calendar calendar; +- +- public JspCalendar() { +- calendar = Calendar.getInstance(); +- Date trialTime = new Date(); +- calendar.setTime(trialTime); +- } +- +- +- public int getYear() { +- return calendar.get(Calendar.YEAR); +- } +- +- public String getMonth() { +- int m = getMonthInt(); +- String[] months = new String [] { "January", "February", "March", +- "April", "May", "June", +- "July", "August", "September", +- "October", "November", "December" }; +- if (m > 12) { +- return "Unknown to Man"; +- } +- +- return months[m - 1]; +- +- } +- +- public String getDay() { +- int x = getDayOfWeek(); +- String[] days = new String[] {"Sunday", "Monday", "Tuesday", "Wednesday", +- "Thursday", "Friday", "Saturday"}; +- +- if (x > 7) { +- return "Unknown to Man"; +- } +- +- return days[x - 1]; +- +- } +- +- public int getMonthInt() { +- return 1 + calendar.get(Calendar.MONTH); +- } +- +- public String getDate() { +- return getMonthInt() + "/" + getDayOfMonth() + "/" + getYear(); +- } +- +- public String getCurrentDate() { +- Date dt = new Date (); +- calendar.setTime (dt); +- return getMonthInt() + "/" + getDayOfMonth() + "/" + getYear(); +- +- } +- +- public String getNextDate() { +- calendar.set (Calendar.DAY_OF_MONTH, getDayOfMonth() + 1); +- return getDate (); +- } +- +- public String getPrevDate() { +- calendar.set (Calendar.DAY_OF_MONTH, getDayOfMonth() - 1); +- return getDate (); +- } +- +- public String getTime() { +- return getHour() + ":" + getMinute() + ":" + getSecond(); +- } +- +- public int getDayOfMonth() { +- return calendar.get(Calendar.DAY_OF_MONTH); +- } +- +- public int getDayOfYear() { +- return calendar.get(Calendar.DAY_OF_YEAR); +- } +- +- public int getWeekOfYear() { +- return calendar.get(Calendar.WEEK_OF_YEAR); +- } +- +- public int getWeekOfMonth() { +- return calendar.get(Calendar.WEEK_OF_MONTH); +- } +- +- public int getDayOfWeek() { +- return calendar.get(Calendar.DAY_OF_WEEK); +- } +- +- public int getHour() { +- return calendar.get(Calendar.HOUR_OF_DAY); +- } +- +- public int getMinute() { +- return calendar.get(Calendar.MINUTE); +- } +- +- +- public int getSecond() { +- return calendar.get(Calendar.SECOND); +- } +- +- +- public int getEra() { +- return calendar.get(Calendar.ERA); +- } +- +- public String getUSTimeZone() { +- String[] zones = new String[] {"Hawaii", "Alaskan", "Pacific", +- "Mountain", "Central", "Eastern"}; +- +- return zones[10 + getZoneOffset()]; +- } +- +- public int getZoneOffset() { +- return calendar.get(Calendar.ZONE_OFFSET)/(60*60*1000); +- } +- +- +- public int getDSTOffset() { +- return calendar.get(Calendar.DST_OFFSET)/(60*60*1000); +- } +- +- +- public int getAMPM() { +- return calendar.get(Calendar.AM_PM); +- } +-} +- +- +diff --git a/webapps/examples/WEB-INF/classes/cal/TableBean.java b/webapps/examples/WEB-INF/classes/cal/TableBean.java +deleted file mode 100644 +index 9f1cc4a6cf7d..000000000000 +--- a/webapps/examples/WEB-INF/classes/cal/TableBean.java ++++ /dev/null +@@ -1,106 +0,0 @@ +-/* +- * 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 cal; +- +-import java.util.Map; +-import java.util.concurrent.ConcurrentHashMap; +- +-import javax.servlet.http.HttpServletRequest; +- +-public class TableBean { +- +- private final Map table; +- private final JspCalendar JspCal; +- private Entries entries; +- private String date; +- private String name = null; +- private String email = null; +- private boolean processError = false; +- +- public TableBean() { +- this.table = new ConcurrentHashMap<>(10); +- this.JspCal = new JspCalendar(); +- this.date = JspCal.getCurrentDate(); +- } +- +- public void setName(String nm) { +- this.name = nm; +- } +- +- public String getName() { +- return this.name; +- } +- +- public void setEmail(String mail) { +- this.email = mail; +- } +- +- public String getEmail() { +- return this.email; +- } +- +- public String getDate() { +- return this.date; +- } +- +- public Entries getEntries() { +- return this.entries; +- } +- +- public void processRequest(HttpServletRequest request) { +- +- // Get the name and e-mail. +- this.processError = false; +- if (name == null || name.equals("")) { +- setName(request.getParameter("name")); +- } +- if (email == null || email.equals("")) { +- setEmail(request.getParameter("email")); +- } +- if (name == null || email == null || name.equals("") +- || email.equals("")) { +- this.processError = true; +- return; +- } +- +- // Get the date. +- String dateR = request.getParameter("date"); +- if (dateR == null) { +- date = JspCal.getCurrentDate(); +- } else if (dateR.equalsIgnoreCase("next")) { +- date = JspCal.getNextDate(); +- } else if (dateR.equalsIgnoreCase("prev")) { +- date = JspCal.getPrevDate(); +- } +- +- entries = table.get(date); +- if (entries == null) { +- entries = new Entries(); +- table.put(date, entries); +- } +- +- // If time is provided add the event. +- String time = request.getParameter("time"); +- if (time != null) { +- entries.processRequest(request, time); +- } +- } +- +- public boolean getProcessError() { +- return this.processError; +- } +-} +diff --git a/webapps/examples/jsp/cal/cal1.jsp b/webapps/examples/jsp/cal/cal1.jsp +deleted file mode 100644 +index ce29c13f9608..000000000000 +--- a/webapps/examples/jsp/cal/cal1.jsp ++++ /dev/null +@@ -1,94 +0,0 @@ +-<%-- +- 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. +---%> +-<%@page contentType="text/html; charset=UTF-8" %> +- +- +- Calendar: A JSP APPLICATION +- +- +- +- +- +-<%@ page language="java" import="cal.*" %> +- +- +-<% +- table.processRequest(request); +- if (table.getProcessError() == false) { +-%> +- +- +-
    +-

NameValue
<%= util.HTMLFilter.filter(name) %><%= util.HTMLFilter.filter(String.valueOf(session.getAttribute(name))) %><%= util.HTMLFilter.filter(value) %>delete
<%= util.HTMLFilter.filter(name) %><%= util.HTMLFilter.filter(value) %>deletedelete
CartsExecuteExecuteSource
+- +- +- +-
prev +- Calendar:<%= table.getDate() %> next +-
+- +- +- +- +- +- +- +- +-<% +- for(int i=0; i +- +- +- +- +-<% +- } +-%> +- +-
Time Appointment
+- > +- <%= entr.getHour() %> +- > +- <% out.print(util.HTMLFilter.filter(entr.getDescription())); %> +-
+-
+- +- +- +- +- +- +-
<% out.print(util.HTMLFilter.filter(table.getName())); %> : +- <% out.print(util.HTMLFilter.filter(table.getEmail())); %>
+- +- +-<% +- } else { +-%> +- +- You must enter your name and email address correctly. +- +-<% +- } +-%> +- +- +- +- +- +- +diff --git a/webapps/examples/jsp/cal/cal2.jsp b/webapps/examples/jsp/cal/cal2.jsp +deleted file mode 100644 +index e7e14d8e0468..000000000000 +--- a/webapps/examples/jsp/cal/cal2.jsp ++++ /dev/null +@@ -1,45 +0,0 @@ +-<%-- +- 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. +---%> +-<%@page contentType="text/html; charset=UTF-8" %> +- +- +- Calendar: A JSP APPLICATION +- +- +- +- +- +- +-<% +- String time = request.getParameter ("time"); +-%> +- +- Please add the following event: +-

Date <%= table.getDate() %> +-
Time <%= util.HTMLFilter.filter(time) %>

+-
+-
+-
+-
+-
+-

Description of the event

+-
+-
+- +- +- +- +diff --git a/webapps/examples/jsp/cal/calendar.html b/webapps/examples/jsp/cal/calendar.html +deleted file mode 100644 +index a0a3ea184134..000000000000 +--- a/webapps/examples/jsp/cal/calendar.html ++++ /dev/null +@@ -1,43 +0,0 @@ +- +- +- +- +-Untitled Document +- +- +- +- +-

+- +-

Source Code for Calendar Example.
+-

cal1.jsp +-

+-

cal2.jsp +-

+- +-
+-

Beans. +-

TableBean +-

+-

Entries +-

+-

Entry +-

+- +- +- +diff --git a/webapps/examples/jsp/cal/login.html b/webapps/examples/jsp/cal/login.html +deleted file mode 100644 +index 8a62eca07b4d..000000000000 +--- a/webapps/examples/jsp/cal/login.html ++++ /dev/null +@@ -1,47 +0,0 @@ +- +- +- +- +- Login page for the calendar. +- +- +- +-
+- +- Please Enter the following information: +- +-
+-
+- +- Name +- +-
+- Email +- +-
+- +- +-
+-
+- Note: This application does not implement the complete +-functionality of a typical calendar application. It demonstrates a way JSP can +-be used with HTML tables and forms. +- +-
+- +- +diff --git a/webapps/examples/jsp/index.html b/webapps/examples/jsp/index.html +index dc25005b2710..ed2da43b9a12 100644 +--- a/webapps/examples/jsp/index.html ++++ b/webapps/examples/jsp/index.html +@@ -249,14 +249,6 @@

JSP 1.2 Examples

+ Source + + +- +-Calendar +- +-Execute +- +-Source +- +- + + Include + diff --git a/CVE-2024-54677-9.patch b/CVE-2024-54677-9.patch new file mode 100644 index 0000000..aca934e --- /dev/null +++ b/CVE-2024-54677-9.patch @@ -0,0 +1,22 @@ +From 9ffd23fc27f5d1fc95bf97e5cea175c8968f4533 Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Fri, 6 Dec 2024 10:44:05 +0000 +Subject: [PATCH] Revert change made for testing + +--- + webapps/examples/WEB-INF/classes/RequestHeaderExample.java | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/webapps/examples/WEB-INF/classes/RequestHeaderExample.java b/webapps/examples/WEB-INF/classes/RequestHeaderExample.java +index e32f8c233674..b324e0250d8a 100644 +--- a/webapps/examples/WEB-INF/classes/RequestHeaderExample.java ++++ b/webapps/examples/WEB-INF/classes/RequestHeaderExample.java +@@ -73,7 +73,7 @@ protected boolean prefersJSON(String acceptHeader) { + + // text/html, application/html, etc. + if (accept.contains("html")) { +- return true; ++ return false; + } + } + return false; diff --git a/CVE-2024-54677-pre.patch b/CVE-2024-54677-pre.patch new file mode 100644 index 0000000..bcc11b7 --- /dev/null +++ b/CVE-2024-54677-pre.patch @@ -0,0 +1,440 @@ +From 5adf342f83eebd5a5e0a83141c56955a25f3a0c3 Mon Sep 17 00:00:00 2001 +From: Mark Thomas +Date: Mon, 2 Dec 2024 14:19:14 +0000 +Subject: [PATCH] Code clean-up - formatting. No functional change + +Origin: https://github.com/apache/tomcat/commit/5adf342f83eebd5a5e0a83141c56955a25f3a0c3 +--- + .../WEB-INF/classes/CookieExample.java | 32 +++++------- + .../WEB-INF/classes/HelloWorldExample.java | 19 +++---- + .../WEB-INF/classes/RequestHeaderExample.java | 49 ++++++------------- + .../WEB-INF/classes/RequestInfoExample.java | 25 ++++------ + .../WEB-INF/classes/RequestParamExample.java | 22 +++------ + .../WEB-INF/classes/ServletToJsp.java | 19 ++++--- + .../WEB-INF/classes/SessionExample.java | 23 +++------ + 7 files changed, 67 insertions(+), 122 deletions(-) + +diff --git a/webapps/examples/WEB-INF/classes/CookieExample.java b/webapps/examples/WEB-INF/classes/CookieExample.java +index cbf375e861bc..32eb1f806ce8 100644 +--- a/webapps/examples/WEB-INF/classes/CookieExample.java ++++ b/webapps/examples/WEB-INF/classes/CookieExample.java +@@ -40,11 +40,8 @@ public class CookieExample extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override +- public void doGet(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { +- ResourceBundle rb = ResourceBundle.getBundle("LocalStrings",request.getLocale()); ++ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ++ ResourceBundle rb = ResourceBundle.getBundle("LocalStrings", request.getLocale()); + + String cookieName = request.getParameter("cookiename"); + String cookieValue = request.getParameter("cookievalue"); +@@ -75,11 +72,11 @@ public void doGet(HttpServletRequest request, + // addition of a PathInfo issue + + out.println(""); +- out.println("\"view"); ++ out.println( ++ "\"view"); + out.println(""); +- out.println("\"return\""); ++ out.println( ++ "\"return\""); + + out.println("

" + title + "

"); + +@@ -95,9 +92,8 @@ public void doGet(HttpServletRequest request, + String cName = cookie.getName(); + String cValue = cookie.getValue(); + out.print("Cookie Name: " + HTMLFilter.filter(cName) + "
"); +- out.println(" Cookie Value: " +- + HTMLFilter.filter(CookieFilter.filter(cName, cValue, sessionId)) +- + "

"); ++ out.println(" Cookie Value: " + HTMLFilter.filter(CookieFilter.filter(cName, cValue, sessionId)) + ++ "

"); + } + } else { + out.println(rb.getString("cookies.no-cookies")); +@@ -106,10 +102,8 @@ public void doGet(HttpServletRequest request, + if (aCookie != null) { + out.println("

"); + out.println(rb.getString("cookies.set") + "
"); +- out.print(rb.getString("cookies.name") + " " +- + HTMLFilter.filter(cookieName) + "
"); +- out.print(rb.getString("cookies.value") + " " +- + HTMLFilter.filter(cookieValue)); ++ out.print(rb.getString("cookies.name") + " " + HTMLFilter.filter(cookieName) + "
"); ++ out.print(rb.getString("cookies.value") + " " + HTMLFilter.filter(cookieValue)); + } + + out.println("

"); +@@ -128,13 +122,9 @@ public void doGet(HttpServletRequest request, + } + + @Override +- public void doPost(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { ++ public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + doGet(request, response); + } + + } + +- +diff --git a/webapps/examples/WEB-INF/classes/HelloWorldExample.java b/webapps/examples/WEB-INF/classes/HelloWorldExample.java +index 15911e23af85..346733aba9ab 100644 +--- a/webapps/examples/WEB-INF/classes/HelloWorldExample.java ++++ b/webapps/examples/WEB-INF/classes/HelloWorldExample.java +@@ -1,3 +1,4 @@ ++ + /* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with +@@ -34,12 +35,8 @@ public class HelloWorldExample extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override +- public void doGet(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { +- ResourceBundle rb = +- ResourceBundle.getBundle("LocalStrings",request.getLocale()); ++ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ++ ResourceBundle rb = ResourceBundle.getBundle("LocalStrings", request.getLocale()); + response.setContentType("text/html"); + response.setCharacterEncoding("UTF-8"); + PrintWriter out = response.getWriter(); +@@ -64,16 +61,14 @@ public void doGet(HttpServletRequest request, + // addition of a PathInfo issue + + out.println(""); +- out.println("\"view"); ++ out.println( ++ "\"view"); + out.println(""); +- out.println("\"return\""); ++ out.println( ++ "\"return\""); + out.println("

" + title + "

"); + out.println(""); + out.println(""); + } + } + +- +- +diff --git a/webapps/examples/WEB-INF/classes/RequestHeaderExample.java b/webapps/examples/WEB-INF/classes/RequestHeaderExample.java +index df2d2d51f78a..98c0e6a9878b 100644 +--- a/webapps/examples/WEB-INF/classes/RequestHeaderExample.java ++++ b/webapps/examples/WEB-INF/classes/RequestHeaderExample.java +@@ -42,10 +42,7 @@ public class RequestHeaderExample extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override +- public void doGet(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { ++ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + if (prefersJSON(request.getHeader("Accept"))) { + renderJSON(request, response); + } else { +@@ -54,16 +51,12 @@ public void doGet(HttpServletRequest request, + } + + /** +- * Returns true if the client appears to prefer a JSON response, +- * false otherwise. +- * +- * Note that this method is not very pedantic and uses only a very lazy +- * algorithm for checking whether JSON is "preferred". ++ * Returns true if the client appears to prefer a JSON response, false otherwise. Note that this method is not very ++ * pedantic and uses only a very lazy algorithm for checking whether JSON is "preferred". + * + * @param acceptHeader The value of the HTTP "Accept" header from the client. + * +- * @return true if the client appears to prefer a JSON response, +- * false otherwise. ++ * @return true if the client appears to prefer a JSON response, false otherwise. + */ + protected boolean prefersJSON(String acceptHeader) { + if (null == acceptHeader) { +@@ -87,11 +80,8 @@ protected boolean prefersJSON(String acceptHeader) { + return false; + } + +- protected void renderHTML(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException +- { +- ResourceBundle rb = ResourceBundle.getBundle("LocalStrings",request.getLocale()); ++ protected void renderHTML(HttpServletRequest request, HttpServletResponse response) throws IOException { ++ ResourceBundle rb = ResourceBundle.getBundle("LocalStrings", request.getLocale()); + + response.setContentType("text/html"); + response.setCharacterEncoding("UTF-8"); +@@ -113,11 +103,11 @@ protected void renderHTML(HttpServletRequest request, + // addition of a PathInfo issue + + out.println(""); +- out.println("\"view"); ++ out.println( ++ "\"view"); + out.println(""); +- out.println("\"return\""); ++ out.println( ++ "\"return\""); + + out.println("

" + title + "

"); + out.println(""); +@@ -143,9 +133,7 @@ protected void renderHTML(HttpServletRequest request, + out.println("
"); + } + +- protected void renderJSON(HttpServletRequest request, HttpServletResponse response) +- throws IOException +- { ++ protected void renderJSON(HttpServletRequest request, HttpServletResponse response) throws IOException { + response.setContentType("application/json"); + response.setCharacterEncoding("UTF-8"); + +@@ -157,14 +145,10 @@ protected void renderJSON(HttpServletRequest request, HttpServletResponse respon + String headerName = e.nextElement(); + String headerValue = request.getHeader(headerName); + +- out.append("{\"") +- .append(JSONFilter.escape(headerName)) +- .append("\":\"") +- .append(JSONFilter.escape(headerValue)) +- .append("\"}") +- ; ++ out.append("{\"").append(JSONFilter.escape(headerName)).append("\":\"") ++ .append(JSONFilter.escape(headerValue)).append("\"}"); + +- if(e.hasMoreElements()) { ++ if (e.hasMoreElements()) { + out.append(','); + } + } +@@ -173,10 +157,7 @@ protected void renderJSON(HttpServletRequest request, HttpServletResponse respon + } + + @Override +- public void doPost(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { ++ public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + doGet(request, response); + } + +diff --git a/webapps/examples/WEB-INF/classes/RequestInfoExample.java b/webapps/examples/WEB-INF/classes/RequestInfoExample.java +index 9ea4668ad42d..57665bb2c51b 100644 +--- a/webapps/examples/WEB-INF/classes/RequestInfoExample.java ++++ b/webapps/examples/WEB-INF/classes/RequestInfoExample.java +@@ -37,11 +37,8 @@ public class RequestInfoExample extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override +- public void doGet(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { +- ResourceBundle rb = ResourceBundle.getBundle("LocalStrings",request.getLocale()); ++ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ++ ResourceBundle rb = ResourceBundle.getBundle("LocalStrings", request.getLocale()); + + response.setContentType("text/html"); + response.setCharacterEncoding("UTF-8"); +@@ -64,11 +61,11 @@ public void doGet(HttpServletRequest request, + // addition of a PathInfo issue + + out.println(""); +- out.println("\"view"); ++ out.println( ++ "\"view"); + out.println(""); +- out.println("\"return\""); ++ out.println( ++ "\"return\""); + + out.println("

" + title + "

"); + out.println(""); + +- String cipherSuite= +- (String)request.getAttribute("javax.servlet.request.cipher_suite"); +- if(cipherSuite!=null){ ++ String cipherSuite = (String) request.getAttribute("javax.servlet.request.cipher_suite"); ++ if (cipherSuite != null) { + out.println("
"); +@@ -93,9 +90,8 @@ public void doGet(HttpServletRequest request, + out.println(HTMLFilter.filter(request.getRemoteAddr())); + out.println("
"); + out.println("SSLCipherSuite:"); + out.println(""); +@@ -107,10 +103,7 @@ public void doGet(HttpServletRequest request, + } + + @Override +- public void doPost(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { ++ public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + doGet(request, response); + } + +diff --git a/webapps/examples/WEB-INF/classes/RequestParamExample.java b/webapps/examples/WEB-INF/classes/RequestParamExample.java +index cbcc3712b6d4..69482936c344 100644 +--- a/webapps/examples/WEB-INF/classes/RequestParamExample.java ++++ b/webapps/examples/WEB-INF/classes/RequestParamExample.java +@@ -37,11 +37,8 @@ public class RequestParamExample extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override +- public void doGet(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { +- ResourceBundle rb = ResourceBundle.getBundle("LocalStrings",request.getLocale()); ++ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ++ ResourceBundle rb = ResourceBundle.getBundle("LocalStrings", request.getLocale()); + + response.setContentType("text/html"); + response.setCharacterEncoding("UTF-8"); +@@ -58,18 +55,18 @@ public void doGet(HttpServletRequest request, + + // img stuff not req'd for source code HTML showing + +- // all links relative ++ // all links relative + + // XXX + // making these absolute till we work out the + // addition of a PathInfo issue + + out.println(""); +- out.println("\"view"); ++ out.println( ++ "\"view"); + out.println(""); +- out.println("\"return\""); ++ out.println( ++ "\"return\""); + + out.println("

" + title + "

"); + String firstName = request.getParameter("firstname"); +@@ -101,10 +98,7 @@ public void doGet(HttpServletRequest request, + } + + @Override +- public void doPost(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { ++ public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + doGet(request, response); + } + +diff --git a/webapps/examples/WEB-INF/classes/ServletToJsp.java b/webapps/examples/WEB-INF/classes/ServletToJsp.java +index a4903a9bba74..e83bbf377620 100644 +--- a/webapps/examples/WEB-INF/classes/ServletToJsp.java ++++ b/webapps/examples/WEB-INF/classes/ServletToJsp.java +@@ -24,16 +24,15 @@ public class ServletToJsp extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override +- public void doGet (HttpServletRequest request, +- HttpServletResponse response) { ++ public void doGet(HttpServletRequest request, HttpServletResponse response) { + +- try { +- // Set the attribute and Forward to hello.jsp +- request.setAttribute ("servletName", "servletToJsp"); +- getServletConfig().getServletContext().getRequestDispatcher( +- "/jsp/jsptoserv/hello.jsp").forward(request, response); +- } catch (Exception ex) { +- ex.printStackTrace (); +- } ++ try { ++ // Set the attribute and Forward to hello.jsp ++ request.setAttribute("servletName", "servletToJsp"); ++ getServletConfig().getServletContext().getRequestDispatcher("/jsp/jsptoserv/hello.jsp").forward(request, ++ response); ++ } catch (Exception ex) { ++ ex.printStackTrace(); ++ } + } + } +diff --git a/webapps/examples/WEB-INF/classes/SessionExample.java b/webapps/examples/WEB-INF/classes/SessionExample.java +index c71ef5f743bb..724b9b437d67 100644 +--- a/webapps/examples/WEB-INF/classes/SessionExample.java ++++ b/webapps/examples/WEB-INF/classes/SessionExample.java +@@ -40,11 +40,8 @@ public class SessionExample extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override +- public void doGet(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { +- ResourceBundle rb = ResourceBundle.getBundle("LocalStrings",request.getLocale()); ++ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { ++ ResourceBundle rb = ResourceBundle.getBundle("LocalStrings", request.getLocale()); + + response.setContentType("text/html"); + response.setCharacterEncoding("UTF-8"); +@@ -68,11 +65,11 @@ public void doGet(HttpServletRequest request, + // addition of a PathInfo issue + + out.println(""); +- out.println("\"view"); ++ out.println( ++ "\"view"); + out.println(""); +- out.println("\"return\""); ++ out.println( ++ "\"return\""); + + out.println("

" + title + "

"); + +@@ -96,8 +93,7 @@ public void doGet(HttpServletRequest request, + while (names.hasMoreElements()) { + String name = names.nextElement(); + String value = session.getAttribute(name).toString(); +- out.println(HTMLFilter.filter(name) + " = " +- + HTMLFilter.filter(value) + "
"); ++ out.println(HTMLFilter.filter(name) + " = " + HTMLFilter.filter(value) + "
"); + } + + out.println("

"); +@@ -137,10 +133,7 @@ public void doGet(HttpServletRequest request, + } + + @Override +- public void doPost(HttpServletRequest request, +- HttpServletResponse response) +- throws IOException, ServletException +- { ++ public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + doGet(request, response); + } + diff --git a/tomcat.spec b/tomcat.spec index c1f4f66..a8e25ba 100644 --- a/tomcat.spec +++ b/tomcat.spec @@ -23,7 +23,7 @@ Name: tomcat Epoch: 1 Version: %{major_version}.%{minor_version}.%{micro_version} -Release: 3 +Release: 4 Summary: Apache Servlet/JSP Engine, RI for Servlet %{servletspec}/JSP %{jspspec} API License: Apache-2.0 @@ -52,6 +52,18 @@ Patch4: rhbz-1857043.patch Patch6: remove-bnd-annotation.patch Patch7: build-with-jdk-1.8.patch Patch8: CVE-2024-52318.patch +Patch9: CVE-2024-50379-1.patch +Patch10: CVE-2024-50379-2.patch +Patch11: CVE-2024-54677-pre.patch +Patch12: CVE-2024-54677-1.patch +Patch13: CVE-2024-54677-2.patch +Patch14: CVE-2024-54677-3.patch +Patch15: CVE-2024-54677-4.patch +Patch16: CVE-2024-54677-5.patch +Patch17: CVE-2024-54677-6.patch +Patch18: CVE-2024-54677-7.patch +Patch19: CVE-2024-54677-8.patch +Patch20: CVE-2024-54677-9.patch BuildArch: noarch @@ -418,6 +430,9 @@ fi %{appdir}/docs %changelog +* Wed Dec 18 2024 wangkai <13474090681@163.com> - 1:9.0.96-4 +- Fix CVE-2024-50379 CVE-2024-54677 + * Tue Nov 26 2024 wangkai <13474090681@163.com> - 1:9.0.96-3 - Add requires ecj for fix server error