478 lines
18 KiB
Diff
Executable File
478 lines
18 KiB
Diff
Executable File
From: Markus Koschany <apo@debian.org>
|
|
Date: Sat, 3 Jul 2021 22:05:57 +0200
|
|
Subject: CVE-2020-27216
|
|
|
|
Origin: https://github.com/eclipse/jetty.project/commit/53e0e0e9b25a6309bf24ee3b10984f4145701edb
|
|
Origin: https://github.com/eclipse/jetty.project/commit/9ad6beb80543b392c91653f6bfce233fc75b9d5f
|
|
---
|
|
.../eclipse/jetty/webapp/WebInfConfiguration.java | 20 +--
|
|
.../server/session/InfinispanTestSupport.java | 173 +++++++++++++--------
|
|
.../test/java/org/eclipse/jetty/TestServer.java | 54 +++----
|
|
3 files changed, 135 insertions(+), 112 deletions(-)
|
|
|
|
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
|
|
index b94f788..19663bc 100644
|
|
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
|
|
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
|
|
@@ -24,6 +24,8 @@ import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
import java.net.URL;
|
|
import java.net.URLClassLoader;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
@@ -384,14 +386,10 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|
@Override
|
|
public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception
|
|
{
|
|
- File tmpDir=File.createTempFile(WebInfConfiguration.getCanonicalNameForWebAppTmpDir(context),"",template.getTempDirectory().getParentFile());
|
|
- if (tmpDir.exists())
|
|
- {
|
|
- IO.delete(tmpDir);
|
|
- }
|
|
- tmpDir.mkdir();
|
|
- tmpDir.deleteOnExit();
|
|
- context.setTempDirectory(tmpDir);
|
|
+ Path tmpDir = Files.createTempDirectory(template.getTempDirectory().getParentFile().toPath(), WebInfConfiguration.getCanonicalNameForWebAppTmpDir(context));
|
|
+ File tmpDirAsFile = tmpDir.toFile();
|
|
+ tmpDirAsFile.deleteOnExit();
|
|
+ context.setTempDirectory(tmpDirAsFile);
|
|
}
|
|
|
|
|
|
@@ -522,11 +520,7 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|
else
|
|
{
|
|
//ensure file will always be unique by appending random digits
|
|
- tmpDir = File.createTempFile(temp, ".dir", parent);
|
|
- //delete the file that was created
|
|
- tmpDir.delete();
|
|
- //and make a directory of the same name
|
|
- tmpDir.mkdirs();
|
|
+ tmpDir = Files.createTempDirectory(parent.toPath(), temp).toFile();
|
|
}
|
|
configureTempDirectory(tmpDir, context);
|
|
|
|
diff --git a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSupport.java b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSupport.java
|
|
index 57ecb1f..663e8dd 100644
|
|
--- a/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSupport.java
|
|
+++ b/tests/test-sessions/test-infinispan-sessions/src/test/java/org/eclipse/jetty/server/session/InfinispanTestSupport.java
|
|
@@ -1,6 +1,6 @@
|
|
//
|
|
// ========================================================================
|
|
-// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
|
+// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
|
// ------------------------------------------------------------------------
|
|
// All rights reserved. This program and the accompanying materials
|
|
// are made available under the terms of the Eclipse Public License v1.0
|
|
@@ -16,38 +16,44 @@
|
|
// ========================================================================
|
|
//
|
|
|
|
-
|
|
package org.eclipse.jetty.server.session;
|
|
|
|
-import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
-import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
-
|
|
import java.io.File;
|
|
+import java.lang.annotation.ElementType;
|
|
+import java.nio.file.Files;
|
|
+import java.nio.file.Path;
|
|
+import java.util.Properties;
|
|
|
|
+import org.eclipse.jetty.toolchain.test.FS;
|
|
import org.eclipse.jetty.util.IO;
|
|
+import org.hibernate.search.cfg.Environment;
|
|
+import org.hibernate.search.cfg.SearchMapping;
|
|
import org.infinispan.Cache;
|
|
-import org.infinispan.configuration.cache.Configuration;
|
|
import org.infinispan.configuration.cache.ConfigurationBuilder;
|
|
+import org.infinispan.configuration.cache.ConfigurationChildBuilder;
|
|
+import org.infinispan.configuration.cache.Index;
|
|
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
|
|
import org.infinispan.manager.DefaultCacheManager;
|
|
import org.infinispan.manager.EmbeddedCacheManager;
|
|
|
|
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
+
|
|
/**
|
|
* InfinispanTestSupport
|
|
- *
|
|
- *
|
|
*/
|
|
public class InfinispanTestSupport
|
|
{
|
|
- public static final String DEFAULT_CACHE_NAME = "session_test_cache";
|
|
- public Cache _cache;
|
|
-
|
|
+ public static final String DEFAULT_CACHE_NAME = "session_test_cache";
|
|
+ public Cache _cache;
|
|
+
|
|
public ConfigurationBuilder _builder;
|
|
- private File _tmpdir;
|
|
+ private File _tmpdir;
|
|
private boolean _useFileStore;
|
|
+ private boolean _serializeSessionData;
|
|
private String _name;
|
|
- public static EmbeddedCacheManager _manager;
|
|
-
|
|
+ public static EmbeddedCacheManager _manager;
|
|
+
|
|
static
|
|
{
|
|
try
|
|
@@ -59,53 +65,84 @@ public class InfinispanTestSupport
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
-
|
|
-
|
|
-
|
|
-
|
|
- public InfinispanTestSupport ()
|
|
+
|
|
+ public InfinispanTestSupport()
|
|
{
|
|
- this (null);
|
|
+ this(null);
|
|
}
|
|
-
|
|
+
|
|
public InfinispanTestSupport(String cacheName)
|
|
- {
|
|
+ {
|
|
if (cacheName == null)
|
|
- cacheName = DEFAULT_CACHE_NAME+System.currentTimeMillis();
|
|
-
|
|
+ cacheName = DEFAULT_CACHE_NAME + System.currentTimeMillis();
|
|
+
|
|
_name = cacheName;
|
|
_builder = new ConfigurationBuilder();
|
|
}
|
|
-
|
|
- public void setUseFileStore (boolean useFileStore)
|
|
+
|
|
+ public void setUseFileStore(boolean useFileStore)
|
|
{
|
|
_useFileStore = useFileStore;
|
|
}
|
|
-
|
|
- public Cache getCache ()
|
|
+
|
|
+ public void setSerializeSessionData(boolean serializeSessionData)
|
|
{
|
|
- return _cache;
|
|
+ _serializeSessionData = serializeSessionData;
|
|
}
|
|
|
|
- public void setup () throws Exception
|
|
+ public Cache getCache()
|
|
{
|
|
- if (_useFileStore)
|
|
- {
|
|
- _tmpdir = File.createTempFile("infini", "span");
|
|
- _tmpdir.delete();
|
|
- _tmpdir.mkdir();
|
|
- Configuration config = _builder.persistence().addSingleFileStore().location(_tmpdir.getAbsolutePath()).storeAsBinary().build();
|
|
- _manager.defineConfiguration(_name, config);
|
|
- }
|
|
- else
|
|
- {
|
|
- _manager.defineConfiguration(_name, _builder.build());
|
|
- }
|
|
- _cache = _manager.getCache(_name);
|
|
+ return _cache;
|
|
}
|
|
|
|
+ public void setup(Path root) throws Exception
|
|
+ {
|
|
+ Path indexesDir = root.resolve("indexes");
|
|
+ FS.ensureDirExists(indexesDir);
|
|
+
|
|
+ SearchMapping mapping = new SearchMapping();
|
|
+ mapping.entity(SessionData.class).indexed().providedId().property("expiry", ElementType.FIELD).field();
|
|
+ Properties properties = new Properties();
|
|
+ properties.put(Environment.MODEL_MAPPING, mapping);
|
|
+ properties.put("hibernate.search.default.indexBase", indexesDir.toString());
|
|
+
|
|
+ if (_useFileStore)
|
|
+ {
|
|
+ Path tmpDir = Files.createTempDirectory("infinispan");
|
|
+ _tmpdir = tmpDir.toFile();
|
|
+
|
|
+ ConfigurationChildBuilder b = _builder.indexing()
|
|
+ .index(Index.ALL)
|
|
+ .addIndexedEntity(SessionData.class)
|
|
+ .withProperties(properties)
|
|
+ .persistence()
|
|
+ .addSingleFileStore()
|
|
+ .location(_tmpdir.getAbsolutePath());
|
|
+ if (_serializeSessionData)
|
|
+ {
|
|
+ b = b.storeAsBinary().enable();
|
|
+ }
|
|
+
|
|
+ _manager.defineConfiguration(_name, b.build());
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ ConfigurationChildBuilder b = _builder.indexing()
|
|
+ .withProperties(properties)
|
|
+ .index(Index.ALL)
|
|
+ .addIndexedEntity(SessionData.class);
|
|
+
|
|
+ if (_serializeSessionData)
|
|
+ {
|
|
+ b = b.storeAsBinary().enable();
|
|
+ }
|
|
+
|
|
+ _manager.defineConfiguration(_name, b.build());
|
|
+ }
|
|
+ _cache = _manager.getCache(_name);
|
|
+ }
|
|
|
|
- public void teardown () throws Exception
|
|
+ public void teardown() throws Exception
|
|
{
|
|
_cache.clear();
|
|
_manager.removeCache(_name);
|
|
@@ -117,39 +154,41 @@ public class InfinispanTestSupport
|
|
}
|
|
}
|
|
}
|
|
-
|
|
-
|
|
+
|
|
@SuppressWarnings("unchecked")
|
|
- public void createSession (SessionData data)
|
|
- throws Exception
|
|
+ public void createSession(SessionData data)
|
|
+ throws Exception
|
|
{
|
|
- _cache.put(data.getContextPath()+"_"+data.getVhost()+"_"+data.getId(), data);
|
|
+ _cache.put(data.getContextPath() + "_" + data.getVhost() + "_" + data.getId(), data);
|
|
}
|
|
|
|
-
|
|
- public void createUnreadableSession (SessionData data)
|
|
+ public void createUnreadableSession(SessionData data)
|
|
{
|
|
-
|
|
+
|
|
}
|
|
-
|
|
-
|
|
- public boolean checkSessionExists (SessionData data)
|
|
- throws Exception
|
|
+
|
|
+ public boolean checkSessionExists(SessionData data)
|
|
+ throws Exception
|
|
{
|
|
- return (_cache.get(data.getContextPath()+"_"+data.getVhost()+"_"+data.getId()) != null);
|
|
+ return (_cache.get(data.getContextPath() + "_" + data.getVhost() + "_" + data.getId()) != null);
|
|
}
|
|
-
|
|
-
|
|
- public boolean checkSessionPersisted (SessionData data)
|
|
- throws Exception
|
|
+
|
|
+ public boolean checkSessionPersisted(SessionData data)
|
|
+ throws Exception
|
|
{
|
|
- Object obj = _cache.get(data.getContextPath()+"_"+data.getVhost()+"_"+data.getId());
|
|
+
|
|
+ //evicts the object from memory. Forces the cache to fetch the data from file
|
|
+ if (_useFileStore)
|
|
+ {
|
|
+ _cache.evict(data.getContextPath() + "_" + data.getVhost() + "_" + data.getId());
|
|
+ }
|
|
+
|
|
+ Object obj = _cache.get(data.getContextPath() + "_" + data.getVhost() + "_" + data.getId());
|
|
if (obj == null)
|
|
return false;
|
|
-
|
|
+
|
|
SessionData saved = (SessionData)obj;
|
|
-
|
|
-
|
|
+
|
|
//turn an Entity into a Session
|
|
assertEquals(data.getId(), saved.getId());
|
|
assertEquals(data.getContextPath(), saved.getContextPath());
|
|
@@ -168,11 +207,11 @@ public class InfinispanTestSupport
|
|
//same keys
|
|
assertTrue(data.getKeys().equals(saved.getKeys()));
|
|
//same values
|
|
- for (String name:data.getKeys())
|
|
+ for (String name : data.getKeys())
|
|
{
|
|
assertTrue(data.getAttribute(name).equals(saved.getAttribute(name)));
|
|
}
|
|
-
|
|
+
|
|
return true;
|
|
}
|
|
}
|
|
diff --git a/tests/test-webapps/test-jetty-webapp/src/test/java/org/eclipse/jetty/TestServer.java b/tests/test-webapps/test-jetty-webapp/src/test/java/org/eclipse/jetty/TestServer.java
|
|
index a7af064..c1c5dc5 100644
|
|
--- a/tests/test-webapps/test-jetty-webapp/src/test/java/org/eclipse/jetty/TestServer.java
|
|
+++ b/tests/test-webapps/test-jetty-webapp/src/test/java/org/eclipse/jetty/TestServer.java
|
|
@@ -1,6 +1,6 @@
|
|
//
|
|
// ========================================================================
|
|
-// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
|
+// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
|
// ------------------------------------------------------------------------
|
|
// All rights reserved. This program and the accompanying materials
|
|
// are made available under the terms of the Eclipse Public License v1.0
|
|
@@ -18,13 +18,11 @@
|
|
|
|
package org.eclipse.jetty;
|
|
|
|
-import java.io.File;
|
|
import java.io.IOException;
|
|
import java.lang.management.ManagementFactory;
|
|
import java.nio.file.FileSystems;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
-
|
|
import javax.servlet.ServletException;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
@@ -65,11 +63,11 @@ public class TestServer
|
|
((StdErrLog)Log.getLog()).setSource(false);
|
|
|
|
// TODO don't depend on this file structure
|
|
- Path jetty_root = FileSystems.getDefault().getPath(".").toAbsolutePath().normalize();
|
|
- if (!Files.exists(jetty_root.resolve("VERSION.txt")))
|
|
- jetty_root = FileSystems.getDefault().getPath("../../..").toAbsolutePath().normalize();
|
|
- if (!Files.exists(jetty_root.resolve("VERSION.txt")))
|
|
- throw new IllegalArgumentException(jetty_root.toString());
|
|
+ Path jettyRoot = FileSystems.getDefault().getPath(".").toAbsolutePath().normalize();
|
|
+ if (!Files.exists(jettyRoot.resolve("VERSION.txt")))
|
|
+ jettyRoot = FileSystems.getDefault().getPath("../../..").toAbsolutePath().normalize();
|
|
+ if (!Files.exists(jettyRoot.resolve("VERSION.txt")))
|
|
+ throw new IllegalArgumentException(jettyRoot.toString());
|
|
|
|
// Setup Threadpool
|
|
QueuedThreadPool threadPool = new QueuedThreadPool();
|
|
@@ -80,10 +78,9 @@ public class TestServer
|
|
server.manage(threadPool);
|
|
|
|
// Setup JMX
|
|
- MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
|
|
+ MBeanContainer mbContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
|
|
server.addBean(mbContainer);
|
|
server.addBean(Log.getLog());
|
|
-
|
|
|
|
// Common HTTP configuration
|
|
HttpConfiguration config = new HttpConfiguration();
|
|
@@ -92,21 +89,19 @@ public class TestServer
|
|
config.addCustomizer(new SecureRequestCustomizer());
|
|
config.setSendDateHeader(true);
|
|
config.setSendServerVersion(true);
|
|
-
|
|
-
|
|
+
|
|
// Http Connector
|
|
HttpConnectionFactory http = new HttpConnectionFactory(config);
|
|
- ServerConnector httpConnector = new ServerConnector(server,http);
|
|
+ ServerConnector httpConnector = new ServerConnector(server, http);
|
|
httpConnector.setPort(8080);
|
|
httpConnector.setIdleTimeout(30000);
|
|
server.addConnector(httpConnector);
|
|
|
|
-
|
|
// Handlers
|
|
HandlerCollection handlers = new HandlerCollection();
|
|
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
|
handlers.setHandlers(new Handler[]
|
|
- { contexts, new DefaultHandler() });
|
|
+ {contexts, new DefaultHandler()});
|
|
|
|
// Add restart handler to test the ability to save sessions and restart
|
|
RestartHandler restart = new RestartHandler();
|
|
@@ -114,15 +109,14 @@ public class TestServer
|
|
|
|
server.setHandler(restart);
|
|
|
|
-
|
|
// Setup context
|
|
HashLoginService login = new HashLoginService();
|
|
login.setName("Test Realm");
|
|
- login.setConfig(jetty_root.resolve("tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/etc/realm.properties").toString());
|
|
+ login.setConfig(jettyRoot.resolve("tests/test-webapps/test-jetty-webapp/src/main/config/demo-base/etc/realm.properties").toString());
|
|
server.addBean(login);
|
|
|
|
- File log=File.createTempFile("jetty-yyyy_mm_dd", "log");
|
|
- CustomRequestLog requestLog = new CustomRequestLog(log.toString());
|
|
+ Path logPath = Files.createTempFile("jetty-yyyy_mm_dd", "log");
|
|
+ CustomRequestLog requestLog = new CustomRequestLog(logPath.toString());
|
|
server.setRequestLog(requestLog);
|
|
|
|
server.setStopAtShutdown(true);
|
|
@@ -130,23 +124,19 @@ public class TestServer
|
|
WebAppContext webapp = new WebAppContext();
|
|
webapp.setContextPath("/test");
|
|
webapp.setParentLoaderPriority(true);
|
|
- webapp.setResourceBase(jetty_root.resolve("tests/test-webapps/test-jetty-webapp/src/main/webapp").toString());
|
|
- webapp.setAttribute("testAttribute","testValue");
|
|
- File sessiondir=File.createTempFile("sessions",null);
|
|
- if (sessiondir.exists())
|
|
- sessiondir.delete();
|
|
- sessiondir.mkdir();
|
|
- sessiondir.deleteOnExit();
|
|
+ webapp.setResourceBase(jettyRoot.resolve("tests/test-webapps/test-jetty-webapp/src/main/webapp").toString());
|
|
+ webapp.setAttribute("testAttribute", "testValue");
|
|
+ Path sessionDir = Files.createTempDirectory("sessions");
|
|
DefaultSessionCache ss = new DefaultSessionCache(webapp.getSessionHandler());
|
|
FileSessionDataStore sds = new FileSessionDataStore();
|
|
ss.setSessionDataStore(sds);
|
|
- sds.setStoreDir(sessiondir);
|
|
+ sds.setStoreDir(sessionDir.toFile());
|
|
webapp.getSessionHandler().setSessionCache(ss);
|
|
|
|
contexts.addHandler(webapp);
|
|
|
|
ContextHandler srcroot = new ContextHandler();
|
|
- srcroot.setResourceBase(jetty_root.resolve("tests/test-webapps/test-jetty-webapp/src").toString());
|
|
+ srcroot.setResourceBase(jettyRoot.resolve("tests/test-webapps/test-jetty-webapp/src").toString());
|
|
srcroot.setHandler(new ResourceHandler());
|
|
srcroot.setContextPath("/src");
|
|
contexts.addHandler(srcroot);
|
|
@@ -158,17 +148,17 @@ public class TestServer
|
|
|
|
private static class RestartHandler extends HandlerWrapper
|
|
{
|
|
- /* ------------------------------------------------------------ */
|
|
+
|
|
/**
|
|
* @see org.eclipse.jetty.server.handler.HandlerWrapper#handle(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
|
|
*/
|
|
@Override
|
|
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
|
{
|
|
- super.handle(target,baseRequest,request,response);
|
|
+ super.handle(target, baseRequest, request, response);
|
|
if (Boolean.valueOf(request.getParameter("restart")))
|
|
{
|
|
- final Server server=getServer();
|
|
+ final Server server = getServer();
|
|
|
|
new Thread()
|
|
{
|
|
@@ -182,7 +172,7 @@ public class TestServer
|
|
Thread.sleep(100);
|
|
server.start();
|
|
}
|
|
- catch(Exception e)
|
|
+ catch (Exception e)
|
|
{
|
|
LOG.warn(e);
|
|
}
|