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]>.

Reply via email to