diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AllowedResourceAliasChecker.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AllowedResourceAliasChecker.java new file mode 100644 index 000000000000..b9a15ceda450 --- /dev/null +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AllowedResourceAliasChecker.java @@ -0,0 +1,57 @@ +package org.eclipse.jetty.server; + +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.resource.Resource; + +import java.io.File; + +/** + * This will approve an alias to any resource which is not a protected target. + */ +public class AllowedResourceAliasChecker implements ContextHandler.AliasCheck +{ + private static final Logger LOG = Log.getLogger(AllowedResourceAliasChecker.class); + private final ContextHandler _contextHandler; + + public AllowedResourceAliasChecker(ContextHandler contextHandler) + { + _contextHandler = contextHandler; + } + + @Override + public boolean check(String uri, Resource resource) + { + try + { + String baseResourcePath = _contextHandler.getBaseResource().getFile().getCanonicalPath(); + String resourcePath = resource.getFile().getCanonicalPath(); + if (!resourcePath.startsWith(baseResourcePath)) + return false; + + for (String s : _contextHandler.getProtectedTargets()) + { + String protectedTarget = new File(_contextHandler.getBaseResource().getFile(), s).getCanonicalPath(); + if (StringUtil.startsWithIgnoreCase(resourcePath, protectedTarget)) + { + if (resourcePath.length() == protectedTarget.length()) + return false; + + // Check that the target prefix really is a path segment. + char c = resourcePath.charAt(protectedTarget.length()); + if (c == File.separatorChar) + return false; + } + } + } + catch (Throwable t) + { + LOG.warn(t); + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/tests/test-integration/src/test/java/org/eclipse/jetty/test/TestClass.java b/tests/test-integration/src/test/java/org/eclipse/jetty/test/TestClass.java new file mode 100644 index 000000000000..784a89319d29 --- /dev/null +++ b/tests/test-integration/src/test/java/org/eclipse/jetty/test/TestClass.java @@ -0,0 +1,62 @@ +package org.eclipse.jetty.test; + +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.server.AllowedResourceAliasChecker; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.resource.Resource; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.net.URL; + +public class TestClass +{ + private Server _server; + private HttpClient _client; + + @BeforeEach + public void before() throws Exception + { + _server = new Server(8080); + + URL webRootLocation = TestClass.class.getClassLoader().getResource("webroot/index.html"); + URI webRootUri = URI.create(webRootLocation.toURI().toASCIIString().replaceFirst("/index.html$","/")); + System.err.printf("Web Root URI: %s%n",webRootUri); + + ServletContextHandler context = new ServletContextHandler(); + context.setContextPath("/"); + context.setBaseResource(Resource.newResource(webRootUri)); + context.setWelcomeFiles(new String[] { "index.html" }); + context.setProtectedTargets(new String[]{"/web-inf", "/meta-inf"}); + context.getMimeTypes().addMimeMapping("txt","text/plain;charset=utf-8"); + + context.addAliasCheck(new AllowedResourceAliasChecker(context)); + _server.setHandler(context); + context.addServlet(DefaultServlet.class,"/"); + _server.start(); + + _client = new HttpClient(); + _client.start(); + } + + + @AfterEach + public void after() throws Exception + { + _client.stop(); + _server.stop(); + } + + @Test + public void test() throws Exception + { +// ContentResponse response = _client.GET("http://localhost:8080/\\WEB-INF\\web.xml"); +// System.err.println(response); + + _server.join(); + } +} diff --git a/tests/test-integration/src/test/resources/webroot/WEB-INF/web.xml b/tests/test-integration/src/test/resources/webroot/WEB-INF/web.xml new file mode 100644 index 000000000000..55130579d92e --- /dev/null +++ b/tests/test-integration/src/test/resources/webroot/WEB-INF/web.xml @@ -0,0 +1 @@ +should not be able to access this file. \ No newline at end of file diff --git a/tests/test-integration/src/test/resources/webroot/index.html b/tests/test-integration/src/test/resources/webroot/index.html new file mode 100644 index 000000000000..f7dc59cdc6b6 --- /dev/null +++ b/tests/test-integration/src/test/resources/webroot/index.html @@ -0,0 +1,4 @@ + +

hello world

+

body of index.html

+ \ No newline at end of file diff --git a/tests/test-integration/src/test/resources/webroot/org/eclipse/jetty/test.txt b/tests/test-integration/src/test/resources/webroot/org/eclipse/jetty/test.txt new file mode 100644 index 000000000000..472c7bb03594 --- /dev/null +++ b/tests/test-integration/src/test/resources/webroot/org/eclipse/jetty/test.txt @@ -0,0 +1 @@ +this is test .txt file and safe to access \ No newline at end of file