Browse Source

Added delay for requests on invalid vault ids. Issue #319

Markus Kreusch 9 năm trước cách đây
mục cha
commit
429b26f3d8

+ 21 - 7
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WindowsCompatibilityServlet.java

@@ -11,6 +11,8 @@ package org.cryptomator.frontend.webdav;
 import java.io.IOException;
 import java.util.EnumSet;
 
+import javax.inject.Inject;
+import javax.inject.Singleton;
 import javax.servlet.DispatcherType;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
@@ -21,12 +23,24 @@ import org.cryptomator.frontend.webdav.filters.LoopbackFilter;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
 
-/**
- * The server needs to respond to requests to the root resource, because Windows is stupid. 
- */
-public class WindowsCompatibilityServlet extends HttpServlet {
+@Singleton
+class DefaultServlet extends HttpServlet {
 	
 	private static final String ROOT_PATH = "/";
+	private static final String WILDCARD = "/*";
+	
+	private final Tarpit tarpit;
+	
+	@Inject
+	public DefaultServlet(Tarpit tarpit) {
+		this.tarpit = tarpit;
+	}
+	
+	@Override
+	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+		tarpit.handle(req);
+		super.service(req, resp);
+	}
 	
 	@Override
 	protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
@@ -36,11 +50,11 @@ public class WindowsCompatibilityServlet extends HttpServlet {
 		resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
 	}
 	
-	public static ServletContextHandler createServletContextHandler() {
+	public ServletContextHandler createServletContextHandler() {
 		final ServletContextHandler servletContext = new ServletContextHandler(null, ROOT_PATH, ServletContextHandler.NO_SESSIONS);
-		final ServletHolder servletHolder = new ServletHolder(ROOT_PATH, WindowsCompatibilityServlet.class);
+		final ServletHolder servletHolder = new ServletHolder(ROOT_PATH, this);
 		servletContext.addServlet(servletHolder, ROOT_PATH);
-		servletContext.addFilter(LoopbackFilter.class, ROOT_PATH, EnumSet.of(DispatcherType.REQUEST));
+		servletContext.addFilter(LoopbackFilter.class, WILDCARD, EnumSet.of(DispatcherType.REQUEST));
 		return servletContext;
 	}
 

+ 46 - 0
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/Tarpit.java

@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Markus Kreusch
+ * This file is licensed under the terms of the MIT license.
+ * See the LICENSE.txt file for more info.
+ *******************************************************************************/
+package org.cryptomator.frontend.webdav;
+
+import static java.lang.Math.max;
+import static java.lang.System.currentTimeMillis;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.servlet.http.HttpServletRequest;
+
+@Singleton
+class Tarpit {
+	
+	private static final long DELAY_MS = 10000;
+	
+	@Inject
+	public Tarpit() {}
+	
+	public void handle(HttpServletRequest req) {
+		if (isRequestWithVaultId(req)) {
+			delayExecutionUninterruptibly();
+		}
+	}
+
+	private void delayExecutionUninterruptibly() {
+		long expected = currentTimeMillis() + DELAY_MS;
+		long sleepTime = DELAY_MS;
+		while (expected > currentTimeMillis()) {
+			try {
+				Thread.sleep(sleepTime);
+			} catch (InterruptedException e) {
+				sleepTime = max(0, currentTimeMillis() - expected + 10);
+			}
+		}
+	}
+
+	private boolean isRequestWithVaultId(HttpServletRequest req) {
+		String path = req.getServletPath();
+		return path.matches("^/[a-zA-Z0-9_-]{12}/.*$");
+	}
+
+}

+ 2 - 2
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServer.java

@@ -47,7 +47,7 @@ public class WebDavServer implements FrontendFactory {
 	private final WebDavMounterProvider webdavMounterProvider;
 
 	@Inject
-	WebDavServer(WebDavServletContextFactory servletContextFactory, WebDavMounterProvider webdavMounterProvider) {
+	WebDavServer(WebDavServletContextFactory servletContextFactory, WebDavMounterProvider webdavMounterProvider, DefaultServlet defaultServlet) {
 		final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(MAX_PENDING_REQUESTS);
 		final ThreadPool tp = new QueuedThreadPool(MAX_THREADS, MIN_THREADS, THREAD_IDLE_SECONDS, queue);
 		this.server = new Server(tp);
@@ -56,7 +56,7 @@ public class WebDavServer implements FrontendFactory {
 		this.servletContextFactory = servletContextFactory;
 		this.webdavMounterProvider = webdavMounterProvider;
 		
-		servletCollection.addHandler(WindowsCompatibilityServlet.createServletContextHandler());
+		servletCollection.addHandler(defaultServlet.createServletContextHandler());
 		server.setConnectors(new Connector[] {localConnector});
 		server.setHandler(servletCollection);
 	}

+ 2 - 3
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/WebDavServletContextFactory.java

@@ -35,10 +35,9 @@ import org.eclipse.jetty.servlet.ServletHolder;
 class WebDavServletContextFactory {
 
 	private static final String WILDCARD = "/*";
-
+	
 	@Inject
-	public WebDavServletContextFactory() {
-	}
+	public WebDavServletContextFactory() {}
 
 	/**
 	 * Creates a new Jetty ServletContextHandler, that can be be added to a servletCollection as follows:

+ 11 - 4
main/frontend-webdav/src/test/java/org/cryptomator/frontend/webdav/WindowsCompatibilityServletTest.java

@@ -8,6 +8,8 @@
  *******************************************************************************/
 package org.cryptomator.frontend.webdav;
 
+import static org.mockito.Mockito.mock;
+
 import java.io.IOException;
 
 import javax.servlet.Servlet;
@@ -21,21 +23,26 @@ import org.junit.Test;
 import org.mockito.Mockito;
 
 
-public class WindowsCompatibilityServletTest {
+public class DefaultServletTest {
+	
+	private Tarpit tarpit = mock(Tarpit.class);
+	
+	private DefaultServlet inTest = new DefaultServlet(tarpit);
 	
 	@Test
 	public void testFactory() throws ServletException {
-		ServletHolder[] holders = WindowsCompatibilityServlet.createServletContextHandler().getServletHandler().getServlets();
+		
+		ServletHolder[] holders = inTest.createServletContextHandler().getServletHandler().getServlets();
 		Assert.assertEquals(1, holders.length);
 		ServletHolder holder = holders[0];
 		
 		Servlet servlet = holder.getServlet();
-		Assert.assertTrue(servlet instanceof WindowsCompatibilityServlet);
+		Assert.assertTrue(servlet instanceof DefaultServlet);
 	}
 	
 	@Test
 	public void testResponse() throws IOException, ServletException {
-		final WindowsCompatibilityServlet servlet = new WindowsCompatibilityServlet();
+		final DefaultServlet servlet = inTest;
 		final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
 		final HttpServletResponse response = Mockito.mock(HttpServletResponse.class);