From a6276c30177c61965a4bcf6daa86e0e3cbbef9f1 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 7 Jul 2016 09:11:19 -0700 Subject: [PATCH] Issue #687 - Adding AllowSymLinkAliasCheckerTest + Replicated, in test case form, the example present in the filed issue. All tests pass. --- jetty-server/pom.xml | 17 +- .../handler/AllowSymLinkAliasCheckerTest.java | 182 ++++++++++++++++++ 2 files changed, 194 insertions(+), 5 deletions(-) create mode 100644 jetty-server/src/test/java/org/eclipse/jetty/server/handler/AllowSymLinkAliasCheckerTest.java diff --git a/jetty-server/pom.xml b/jetty-server/pom.xml index 30ce675ce27..5e23b2dbbce 100644 --- a/jetty-server/pom.xml +++ b/jetty-server/pom.xml @@ -36,11 +36,6 @@ - - org.eclipse.jetty.toolchain - jetty-test-helper - test - javax.servlet javax.servlet-api @@ -71,6 +66,18 @@ ${project.version} true + + org.eclipse.jetty.toolchain + jetty-test-helper + test + + + org.eclipse.jetty + jetty-http + ${project.version} + tests + test + org.mockito mockito-core diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AllowSymLinkAliasCheckerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AllowSymLinkAliasCheckerTest.java new file mode 100644 index 00000000000..9655a44d829 --- /dev/null +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AllowSymLinkAliasCheckerTest.java @@ -0,0 +1,182 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.server.handler; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertThat; +import static org.junit.Assume.assumeNoException; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileSystemException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jetty.http.HttpTester; +import org.eclipse.jetty.server.LocalConnector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.toolchain.test.FS; +import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.resource.PathResource; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +@RunWith(Parameterized.class) +public class AllowSymLinkAliasCheckerTest +{ + @Parameterized.Parameters(name = "{0}") + public static List params() + { + List data = new ArrayList<>(); + + data.add(new Object[]{"/testdir/", 200, "text/html", "Directory: /testdir/"}); + data.add(new Object[]{"/testdirlnk/", 200, "text/html", "Directory: /testdirlnk/"}); + data.add(new Object[]{"/testdir/testfile.txt", 200, "text/plain", "Hello TestFile"}); + data.add(new Object[]{"/testdir/testfilelnk.txt", 200, "text/plain", "Hello TestFile"}); + data.add(new Object[]{"/testdirlnk/testfile.txt", 200, "text/plain", "Hello TestFile"}); + data.add(new Object[]{"/testdirlnk/testfilelnk.txt", 200, "text/plain", "Hello TestFile"}); + + return data; + } + + private Server server; + private LocalConnector localConnector; + private Path rootPath; + + @Before + public void setup() throws Exception + { + setupRoot(); + setupServer(); + } + + @After + public void teardown() throws Exception + { + server.stop(); + } + + private void setupRoot() throws IOException + { + rootPath = MavenTestingUtils.getTargetTestingPath(AllowSymLinkAliasCheckerTest.class.getSimpleName()); + FS.ensureEmpty(rootPath); + + Path testdir = rootPath.resolve("testdir"); + FS.ensureDirExists(testdir); + + try + { + Path testdirlnk = rootPath.resolve("testdirlnk"); + // Create a relative symlink testdirlnk -> testdir. + // If we used testdir (Path) from above, this symlink + // would point to an absolute path. + Files.createSymbolicLink(testdirlnk, new File("testdir").toPath()); + } + catch (UnsupportedOperationException | FileSystemException e) + { + // If unable to create symlink, no point testing the rest. + // This is the path that Microsoft Windows takes. + assumeNoException(e); + } + + Path testfileTxt = testdir.resolve("testfile.txt"); + Files.createFile(testfileTxt); + try (OutputStream out = Files.newOutputStream(testfileTxt)) + { + out.write("Hello TestFile".getBytes(StandardCharsets.UTF_8)); + } + + try + { + Path testfileTxtLnk = testdir.resolve("testfilelnk.txt"); + // Create a relative symlink testfilelnk.txt -> testfile.txt. + // If we used testfileTxt (Path) from above, this symlink + // would point to an absolute path. + Files.createSymbolicLink(testfileTxtLnk, new File("testfile.txt").toPath()); + } + catch (UnsupportedOperationException | FileSystemException e) + { + // If unable to create symlink, no point testing the rest. + // This is the path that Microsoft Windows takes. + assumeNoException(e); + } + } + + private void setupServer() throws Exception + { + // Setup server + server = new Server(); + localConnector = new LocalConnector(server); + server.addConnector(localConnector); + + ResourceHandler fileResourceHandler = new ResourceHandler(); + fileResourceHandler.setDirectoriesListed(true); + fileResourceHandler.setWelcomeFiles(new String[]{"index.html"}); + fileResourceHandler.setEtags(true); + + ContextHandler fileResourceContext = new ContextHandler(); + fileResourceContext.setContextPath("/"); + fileResourceContext.setAllowNullPathInfo(true); + fileResourceContext.setHandler(fileResourceHandler); + fileResourceContext.setBaseResource(new PathResource(rootPath)); + + fileResourceContext.clearAliasChecks(); + fileResourceContext.addAliasCheck(new AllowSymLinkAliasChecker()); + + server.setHandler(fileResourceContext); + server.start(); + } + + @Parameterized.Parameter(0) + public String requestURI; + @Parameterized.Parameter(1) + public int expectedResponseStatus; + @Parameterized.Parameter(2) + public String expectedResponseContentType; + @Parameterized.Parameter(3) + public String expectedResponseContentContains; + + public AllowSymLinkAliasCheckerTest() + { + } + + @Test(timeout = 5000) + public void testAccess() throws Exception + { + HttpTester.Request request = HttpTester.newRequest(); + + request.setMethod("GET"); + request.setHeader("Host", "tester"); + request.setURI(requestURI); + + String responseString = localConnector.getResponse(BufferUtil.toString(request.generate())); + assertThat("Response status code", responseString, startsWith("HTTP/1.1 " + expectedResponseStatus + " ")); + assertThat("Response Content-Type", responseString, containsString("\nContent-Type: " + expectedResponseContentType)); + assertThat("Response", responseString, containsString(expectedResponseContentContains)); + } +}