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);
                         }
