This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.security-1.1.4 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-security.git
commit cdc320c46418ad1608371aba493bc925d0bfdf0a Author: Antonio Sanso <[email protected]> AuthorDate: Tue Jun 13 12:15:53 2017 +0000 SLING-6937 - Referrer Filter: Allow Regex User Agent Exclusions git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/security@1798584 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 6 ++++ .../apache/sling/security/impl/ReferrerFilter.java | 40 ++++++++++++++++++---- .../OSGI-INF/metatype/metatype.properties | 3 ++ .../sling/security/impl/ReferrerFilterTest.java | 18 +++++++++- 4 files changed, 59 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 4dd1bea..11a50d0 100644 --- a/pom.xml +++ b/pom.xml @@ -110,6 +110,12 @@ <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.4</version> + <scope>provided</scope> + </dependency> <!-- Testing --> <dependency> <groupId>junit</groupId> diff --git a/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java b/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java index e8ca762..bda2225 100644 --- a/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java +++ b/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java @@ -115,6 +115,12 @@ public class ReferrerFilter implements Filter { @Property(unbounded=PropertyUnbounded.ARRAY, value={"POST", "PUT", "DELETE"}) private static final String PROP_METHODS = "filter.methods"; + private static final String[] DEFAULT_PROP_AGENTS = {}; + + /** Excluded regexp user agents property */ + @Property(unbounded = PropertyUnbounded.ARRAY) + private static final String PROP_EXCLUDED_AGENTS_REGEX = "exclude.agents.regexp"; + /** Do we allow empty referrer? */ @@ -129,6 +135,9 @@ public class ReferrerFilter implements Filter { /** Methods to be filtered. */ private String[] filterMethods; + /** Paths to be excluded */ + private Pattern[] excludedRegexUserAgents; + private ServiceRegistration<Object> configPrinterRegistration; /** @@ -200,7 +209,7 @@ public class ReferrerFilter implements Filter { /** * Create Patterns out of the regexp referrer list */ - private Pattern[] createReferrerPatterns(final String[] regexps) { + private Pattern[] createRegexPatterns(final String[] regexps) { final List<Pattern> patterns = new ArrayList<Pattern>(); for(final String regexp : regexps) { try { @@ -222,7 +231,11 @@ public class ReferrerFilter implements Filter { final String[] allowRegexHosts = defaultIfEmpty(PropertiesUtil.toStringArray(props.get(PROP_HOSTS_REGEX), DEFAULT_PROP_HOSTS), DEFAULT_PROP_HOSTS); - this.allowedRegexReferrers = createReferrerPatterns(allowRegexHosts); + this.allowedRegexReferrers = createRegexPatterns(allowRegexHosts); + + final String[] excludedUserAgents = defaultIfEmpty(PropertiesUtil.toStringArray(props.get(PROP_EXCLUDED_AGENTS_REGEX), + DEFAULT_PROP_AGENTS), DEFAULT_PROP_AGENTS); + this.excludedRegexUserAgents = createRegexPatterns(excludedUserAgents); final Set<String> allowUriReferrers = getDefaultAllowedReferrers(); final String[] allowHosts = defaultIfEmpty(PropertiesUtil.toStringArray(props.get(PROP_HOSTS), @@ -421,6 +434,20 @@ public class ReferrerFilter implements Filter { } /** + * Returns <code>true</code> if the provided user agent matches any present exclusion regexp pattern. + * @param userAgent The user agent string to check + * @return <code>true</code> if the user agent matches any exclusion pattern. + */ + private boolean isExcludedRegexUserAgent(String userAgent) { + for(final Pattern pattern : this.excludedRegexUserAgents) { + if (pattern.matcher(userAgent).matches()) { + return true; + } + } + return false; + } + + /** * @return The <code>defaultProperties</code> if <code>properties</code> contains a single empty string, * <code>properties</code> otherwise. */ @@ -444,12 +471,11 @@ public class ReferrerFilter implements Filter { * @return <code>true</code> if the request is assumed to be sent by a * browser. */ - private boolean isBrowserRequest(final HttpServletRequest request) { + protected boolean isBrowserRequest(final HttpServletRequest request) { final String userAgent = request.getHeader(USER_AGENT); - if (userAgent != null && (userAgent.contains(BROWSER_CLASS_MOZILLA) || userAgent.contains(BROWSER_CLASS_OPERA))) { - return true; - } - return false; + return userAgent != null + && (userAgent.contains(BROWSER_CLASS_MOZILLA) || userAgent.contains(BROWSER_CLASS_OPERA)) + && !isExcludedRegexUserAgent(userAgent); } public class ConfigurationPrinter { diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties index 0905fb1..2ea3998 100644 --- a/src/main/resources/OSGI-INF/metatype/metatype.properties +++ b/src/main/resources/OSGI-INF/metatype/metatype.properties @@ -27,6 +27,9 @@ referrer.name = Apache Sling Referrer Filter referrer.description = Request filter checking the referrer of modification requests. +exclude.agents.regexp.name = Exclude Regexp User Agent +exclude.agents.regexp.description = List of regexp for user agents not to check the referrer. + allow.empty.name = Allow Empty allow.empty.description = Allow an empty or missing referrer diff --git a/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java b/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java index 7eb6d16..1b84bb1 100644 --- a/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java +++ b/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java @@ -28,6 +28,7 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; +import org.apache.commons.lang3.StringUtils; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -45,6 +46,7 @@ public class ReferrerFilterTest { final Map<String, Object> props = new HashMap<String, Object>(){{ put("allow.hosts", new String[]{"relhost"}); put("allow.hosts.regexp", new String[]{"http://([^.]*.)?abshost:80"}); + put("exclude.agents.regexp", new String[]{"[a-zA-Z]*\\/[0-9]*\\.[0-9]*;Some-Agent\\s.*"}); }}; doReturn(reg).when(bundleCtx).registerService(any(String[].class), any(), any(Dictionary.class)); doNothing().when(reg).unregister(); @@ -69,14 +71,21 @@ public class ReferrerFilterTest { Assert.assertEquals(null, filter.getHost("http:/admin:admin@somehost:4343/somewhere")); } - private HttpServletRequest getRequest(final String referrer) { + private HttpServletRequest getRequest(final String referrer, final String userAgent) { final HttpServletRequest request = mock(HttpServletRequest.class); when(request.getMethod()).thenReturn("POST"); when(request.getRequestURI()).thenReturn("http://somehost/somewhere"); when(request.getHeader("referer")).thenReturn(referrer); + if (StringUtils.isNotBlank(userAgent)) { + when(request.getHeader("User-Agent")).thenReturn(userAgent); + } return request; } + private HttpServletRequest getRequest(final String referrer) { + return getRequest(referrer, null); + } + @Test public void testValidRequest() { Assert.assertEquals(false, filter.isValidRequest(getRequest(null))); Assert.assertEquals(true, filter.isValidRequest(getRequest("relative"))); @@ -95,4 +104,11 @@ public class ReferrerFilterTest { Assert.assertEquals(true, filter.isValidRequest(getRequest("http://another.abshost:80"))); Assert.assertEquals(false, filter.isValidRequest(getRequest("http://yet.another.abshost:80"))); } + + @Test public void testIsBrowserRequest() { + String userAgent = "Mozilla/5.0;Some-Agent (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko)"; + Assert.assertEquals(false, filter.isBrowserRequest(getRequest(null, userAgent))); + userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko)"; + Assert.assertEquals(true, filter.isBrowserRequest(getRequest(null, userAgent))); + } } -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
