From 30dade6b5a8b27ea20a52c268c2dfe738d10900d Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Thu, 12 Jan 2012 17:33:52 +0100 Subject: [PATCH] 366472: CrossDomainFilter accepts wildcard domains like *.example.com Signed-off-by: Simone Bordet --- .../jetty/servlets/CrossOriginFilter.java | 31 +++++++++--- .../jetty/servlets/CrossOriginFilterTest.java | 47 +++++++++++++++++++ 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java index f4026369372..173be017da6 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java @@ -18,6 +18,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -229,19 +231,34 @@ public class CrossOriginFilter implements Filter if (origin.trim().length() == 0) continue; - boolean allowed = false; for (String allowedOrigin : allowedOrigins) { - if (allowedOrigin.equals(origin)) + if (allowedOrigin.contains("*")) { - allowed = true; - break; + Matcher matcher = createMatcher(origin,allowedOrigin); + if (matcher.matches()) + return true; + } + else if (allowedOrigin.equals(origin)) + { + return true; } } - if (!allowed) - return false; } - return true; + return false; + } + + private Matcher createMatcher(String origin, String allowedOrigin) + { + String regex = parseAllowedWildcardOriginToRegex(allowedOrigin); + Pattern pattern = Pattern.compile(regex); + return pattern.matcher(origin); + } + + private String parseAllowedWildcardOriginToRegex(String allowedOrigin) + { + String regex = allowedOrigin.replace(".","\\."); + return regex.replace("*",".*"); // we want to be greedy here to match multiple subdomains, thus we use .* } private boolean isSimpleRequest(HttpServletRequest request) diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java index e59051ffbf0..fb8d6bba490 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java @@ -76,6 +76,52 @@ public class CrossOriginFilterTest Assert.assertTrue(latch.await(1, TimeUnit.SECONDS)); } + @Test + public void testSimpleRequestWithMatchingWildcardOrigin() throws Exception + { + FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter()); + String origin = "http://subdomain.example.com"; + filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://*.example.com"); + tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT); + + CountDownLatch latch = new CountDownLatch(1); + tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*"); + + String request = "" + + "GET / HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Origin: " + origin + "\r\n" + + "\r\n"; + String response = tester.getResponses(request); + Assert.assertTrue(response.contains("HTTP/1.1 200")); + Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER)); + Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER)); + Assert.assertTrue(latch.await(1, TimeUnit.SECONDS)); + } + + @Test + public void testSimpleRequestWithMatchingWildcardOriginAndMultipleSubdomains() throws Exception + { + FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter()); + String origin = "http://subdomain.subdomain.example.com"; + filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://*.example.com"); + tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT); + + CountDownLatch latch = new CountDownLatch(1); + tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*"); + + String request = "" + + "GET / HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Origin: " + origin + "\r\n" + + "\r\n"; + String response = tester.getResponses(request); + Assert.assertTrue(response.contains("HTTP/1.1 200")); + Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER)); + Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER)); + Assert.assertTrue(latch.await(1, TimeUnit.SECONDS)); + } + @Test public void testSimpleRequestWithMatchingOrigin() throws Exception { @@ -327,6 +373,7 @@ public class CrossOriginFilterTest public static class ResourceServlet extends HttpServlet { + private static final long serialVersionUID = 1L; private final CountDownLatch latch; public ResourceServlet(CountDownLatch latch)