You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 10:14:44 UTC

[sling-org-apache-sling-security] 02/04: SLING-7030 : ReferrerFilter broken as legacy SCR Annotations are not processed. Apply modified patch from Dominique Jäggi

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.6
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-security.git

commit 30fb46b8122e3f480610507cb13377dd7f2a68e6
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Fri Aug 4 11:28:45 2017 +0000

    SLING-7030 : ReferrerFilter broken as legacy SCR Annotations are not processed. Apply modified patch from  Dominique Jäggi
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/security@1804102 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  36 ++---
 .../apache/sling/security/impl/ReferrerFilter.java | 165 +++++++++++----------
 .../OSGI-INF/metatype/metatype.properties          |  44 ------
 .../sling/security/impl/ReferrerFilterTest.java    |  58 ++++++--
 4 files changed, 142 insertions(+), 161 deletions(-)

diff --git a/pom.xml b/pom.xml
index c054405..8c13e7c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -45,10 +45,6 @@
     <build>
         <plugins>
             <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-scr-plugin</artifactId>
-            </plugin>
-            <plugin>
                 <groupId>org.apache.sling</groupId>
                 <artifactId>maven-sling-plugin</artifactId>
             </plugin>
@@ -56,15 +52,18 @@
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <id>scr-metadata</id>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
                 <configuration>
+                    <exportScr>true</exportScr>
                     <instructions>
                         <Bundle-Category>sling</Bundle-Category>
-                        <Embed-Dependency>
-                            org.apache.sling.commons.osgi;inline=org/apache/sling/commons/osgi/PropertiesUtil.*
-                        </Embed-Dependency>
-                        <Private-Package>
-                            org.apache.sling.security.impl
-                        </Private-Package>
                         <Require-Capability>
                             osgi.implementation;filter:="(&amp;(osgi.implementation=osgi.http)(version=1.0))"
                         </Require-Capability>
@@ -90,33 +89,16 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.scr.annotations</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.api</artifactId>
             <version>2.1.0</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.commons.osgi</artifactId>
-            <version>2.1.0</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
             <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>
-        <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.webconsole</artifactId>
             <version>3.1.0</version>
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 9fef94b..9533a11 100644
--- a/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java
+++ b/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java
@@ -32,7 +32,6 @@ import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
 
@@ -45,29 +44,27 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Properties;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyUnbounded;
-import org.apache.felix.scr.annotations.Service;
-import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-@Component(metatype=true, description="%referrer.description",
-        label="%referrer.name")
-@Properties({
-    @Property(name=HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN, value="/", propertyPrivate=true),
-    @Property(name=HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
-              value="(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=*)", propertyPrivate=true)
-})
-@Service(value=Filter.class)
+@Component(
+        service = Filter.class,
+        property = {
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN + "=/",
+                HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT + "=(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=*)"
+        }
+)
+@Designate(ocd = ReferrerFilter.Config.class)
 public class ReferrerFilter implements Filter {
 
     /**
@@ -91,39 +88,67 @@ public class ReferrerFilter implements Filter {
      */
     private static final String BROWSER_CLASS_OPERA = "Opera";
 
-    /** Logger. */
+    /**
+     * Logger.
+     */
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
-    /** Default value for allow empty. */
-    private static final boolean DEFAULT_ALLOW_EMPTY = false;
-
-    /** Allow empty property. */
-    @Property(boolValue=DEFAULT_ALLOW_EMPTY)
-    private static final String PROP_ALLOW_EMPTY = "allow.empty";
+    @ObjectClassDefinition(
+            name = "Apache Sling Referrer Filter",
+            description = "Request filter checking the referrer of modification requests"
+    )
+    public @interface Config {
 
-    private static final String[] DEFAULT_PROP_HOSTS = {};
-
-    /** Allow referrer uri hosts property. */
-    @Property(unbounded=PropertyUnbounded.ARRAY)
-    private static final String PROP_HOSTS = "allow.hosts";
-
-    /** Allow referrer regex hosts property */
-    @Property(unbounded=PropertyUnbounded.ARRAY)
-    private static final String PROP_HOSTS_REGEX = "allow.hosts.regexp";
+        /**
+         * Allow empty property.
+         */
+        @AttributeDefinition(
+                name = "Allow Empty",
+                description = "Allow an empty or missing referrer"
+        )
+        boolean allow_empty() default false;
 
-    /** Filtered methods property */
-    @Property(unbounded=PropertyUnbounded.ARRAY, value={"POST", "PUT", "DELETE"})
-    private static final String PROP_METHODS = "filter.methods";
+        /**
+         * Allow referrer uri hosts property.
+         */
+        @AttributeDefinition(
+                name = "Allow Hosts",
+                description = "List of allowed hosts for the referrer which are added to the list of default hosts"
+        )
+        String[] allow_hosts() default {};
 
-    private static final String[] DEFAULT_PROP_AGENTS = {};
+        /**
+         * Allow referrer regex hosts property
+         */
+        @AttributeDefinition(
+                name = "Allow Regexp Host",
+                description = "List of allowed regexp for the referrer"
+        )
+        String[] allow_hosts_regexp() default {};
 
-    /** Excluded regexp user agents property */
-    @Property(unbounded = PropertyUnbounded.ARRAY)
-    private static final String PROP_EXCLUDED_AGENTS_REGEX = "exclude.agents.regexp";
+        /**
+         * Filtered methods property
+         */
+        @AttributeDefinition(
+                name = "Filter Methods",
+                description = "These methods are filtered by the filter"
+        )
+        String[] filter_methods() default {"POST", "PUT", "DELETE"};
 
+        /**
+         * Excluded regexp user agents property
+         */
+        @AttributeDefinition(
+                name = "Exclude Regexp User Agent",
+                description = "List of regexp for user agents not to check the referrer"
+        )
+        String[] exclude_agents_regexp() default {};
+    }
 
 
-    /** Do we allow empty referrer? */
+    /**
+     * Do we allow empty referrer?
+     */
     private boolean allowEmpty;
 
     /** Allowed uri referrers */
@@ -144,7 +169,7 @@ public class ReferrerFilter implements Filter {
      * Create a default list of referrers
      */
     private Set<String> getDefaultAllowedReferrers() {
-        final Set<String> referrers = new HashSet<String>();
+        final Set<String> referrers = new HashSet<>();
         try {
             final Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
 
@@ -191,7 +216,7 @@ public class ReferrerFilter implements Filter {
      * Create URLs out of the uri referrer set
      */
     private URL[] createReferrerUrls(final Set<String> referrers) {
-        final List<URL> urls = new ArrayList<URL>();
+        final List<URL> urls = new ArrayList<>();
 
         for(final String ref : referrers) {
             final int pos = ref.indexOf("://");
@@ -210,38 +235,36 @@ public class ReferrerFilter implements Filter {
      * Create Patterns out of the regular expression referrer list
      */
     private Pattern[] createRegexPatterns(final String[] regexps) {
-        final List<Pattern> patterns = new ArrayList<Pattern>();
-        for(final String regexp : regexps) {
-            try {
-                final Pattern pattern  = Pattern.compile(regexp);
-                patterns.add(pattern);
-            } catch (final Exception e) {
-                logger.warn("Unable to create Pattern from {} : {}", new Object[]{regexp, e.getMessage()});
+        final List<Pattern> patterns = new ArrayList<>();
+        if ( regexps != null ) {
+            for(final String regexp : regexps) {
+                try {
+                    final Pattern pattern  = Pattern.compile(regexp);
+                    patterns.add(pattern);
+                } catch (final Exception e) {
+                    logger.warn("Unable to create Pattern from {} : {}", new Object[]{regexp, e.getMessage()});
+                }
             }
         }
         return patterns.toArray(new Pattern[patterns.size()]);
     }
 
     @Activate
-    protected void activate(final BundleContext context, final Map<String, Object> props) {
-        this.allowEmpty = PropertiesUtil.toBoolean(props.get(PROP_ALLOW_EMPTY), DEFAULT_ALLOW_EMPTY);
-
-        final String[] allowRegexHosts = defaultIfEmpty(PropertiesUtil.toStringArray(props.get(PROP_HOSTS_REGEX),
-                DEFAULT_PROP_HOSTS), DEFAULT_PROP_HOSTS);
-        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);
+    protected void activate(final BundleContext context, Config config) {
+        this.allowEmpty = config.allow_empty();
+        this.allowedRegexReferrers = createRegexPatterns(config.allow_hosts_regexp());
+        this.excludedRegexUserAgents = createRegexPatterns(config.exclude_agents_regexp());
 
         final Set<String> allowUriReferrers = getDefaultAllowedReferrers();
-        final String[] allowHosts = defaultIfEmpty(PropertiesUtil.toStringArray(props.get(PROP_HOSTS),
-                DEFAULT_PROP_HOSTS), DEFAULT_PROP_HOSTS);
-        allowUriReferrers.addAll(Arrays.asList(allowHosts));
+        if ( config.allow_hosts() != null ) {
+            allowUriReferrers.addAll(Arrays.asList(config.allow_hosts()));
+        }
         this.allowedUriReferrers = createReferrerUrls(allowUriReferrers);
 
-        this.filterMethods = PropertiesUtil.toStringArray(props.get(PROP_METHODS));
-        if ( this.filterMethods != null && this.filterMethods.length == 1 && (this.filterMethods[0] == null || this.filterMethods[0].trim().length() == 0) ) {
+        this.filterMethods = config.filter_methods();
+        if (this.filterMethods != null
+            &&this.filterMethods.length == 1
+            && (this.filterMethods[0] == null || this.filterMethods[0].trim().length() == 0)) {
             this.filterMethods = null;
         }
         if ( this.filterMethods != null ) {
@@ -259,7 +282,7 @@ public class ReferrerFilter implements Filter {
 
     private ServiceRegistration<Object> registerConfigPrinter(BundleContext bundleContext) {
         final ConfigurationPrinter cfgPrinter = new ConfigurationPrinter();
-        final Dictionary<String, String> serviceProps = new Hashtable<String, String>();
+        final Dictionary<String, String> serviceProps = new Hashtable<>();
         serviceProps.put(Constants.SERVICE_DESCRIPTION,
             "Apache Sling Referrer Filter Configuration Printer");
         serviceProps.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
@@ -445,16 +468,6 @@ public class ReferrerFilter implements Filter {
     }
 
     /**
-     * @return The <code>defaultProperties</code> if <code>properties</code> contains a single empty string,
-     *         <code>properties</code> otherwise.
-     */
-    private String[] defaultIfEmpty(String[] properties, String[] defaultProperties) {
-        return properties.length == 1 && properties[0].trim().length() == 0
-                ? defaultProperties
-                : properties;
-    }
-
-    /**
      * Returns <code>true</code> if the given request can be assumed to be sent
      * by a client browser such as Firefix, Internet Explorer, etc.
      * <p>
diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties
deleted file mode 100644
index 2ea3998..0000000
--- a/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-#  Licensed to the Apache Software Foundation (ASF) under one
-#  or more contributor license agreements.  See the NOTICE file
-#  distributed with this work for additional information
-#  regarding copyright ownership.  The ASF licenses this file
-#  to you under the Apache License, Version 2.0 (the
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing,
-#  software distributed under the License is distributed on an
-#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#  KIND, either express or implied.  See the License for the
-#  specific language governing permissions and limitations
-#  under the License.
-#
-
-#
-# This file contains localization strings for configuration labels and
-# descriptions as used in the metatype.xml descriptor generated by the
-# the SCR plugin
-
-#
-# Referrer Filter
-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
-
-allow.hosts.name = Allow Hosts
-allow.hosts.description = List of allowed hosts for the referrer which are added to the list of default hosts.
-
-
-allow.hosts.regexp.name = Allow Regexp Host
-allow.hosts.regexp.description = List of allowed regexp for the referrer.
-
-filter.methods.name = Filter Methods
-filter.methods.description = These methods are filtered by the filter.
\ No newline at end of file
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 1b84bb1..6214b18 100644
--- a/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java
+++ b/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java
@@ -22,13 +22,11 @@ import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import java.lang.annotation.Annotation;
 import java.util.Dictionary;
-import java.util.HashMap;
-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;
@@ -39,21 +37,51 @@ public class ReferrerFilterTest {
 
     protected ReferrerFilter filter;
 
-    @Before public void setup() {
+    @Before
+    public void setup() {
         filter = new ReferrerFilter();
         final BundleContext bundleCtx = mock(BundleContext.class);
         final ServiceRegistration reg = mock(ServiceRegistration.class);
-        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.*"});
-        }};
+
+        ReferrerFilter.Config config = new ReferrerFilter.Config() {
+            @Override
+            public Class<? extends Annotation> annotationType() {
+                return null;
+            }
+
+            @Override
+            public boolean allow_empty() {
+                return false;
+            }
+
+            @Override
+            public String[] allow_hosts() {
+                return new String[]{"relhost"};
+            }
+
+            @Override
+            public String[] allow_hosts_regexp() {
+                return new String[]{"http://([^.]*.)?abshost:80"};
+            }
+
+            @Override
+            public String[] filter_methods() {
+                return new String[0];
+            }
+
+            @Override
+            public String[] exclude_agents_regexp() {
+                return 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();
-        filter.activate(bundleCtx, props);
+        filter.activate(bundleCtx, config);
     }
 
-    @Test public void testHostName() {
+    @Test
+    public void testHostName() {
         Assert.assertEquals("somehost", filter.getHost("http://somehost").host);
         Assert.assertEquals("somehost", filter.getHost("http://somehost/somewhere").host);
         Assert.assertEquals("somehost", filter.getHost("http://somehost:4242/somewhere").host);
@@ -76,7 +104,7 @@ public class ReferrerFilterTest {
         when(request.getMethod()).thenReturn("POST");
         when(request.getRequestURI()).thenReturn("http://somehost/somewhere");
         when(request.getHeader("referer")).thenReturn(referrer);
-        if (StringUtils.isNotBlank(userAgent)) {
+        if ( userAgent != null && userAgent.length() > 0 ) {
             when(request.getHeader("User-Agent")).thenReturn(userAgent);
         }
         return request;
@@ -86,7 +114,8 @@ public class ReferrerFilterTest {
         return getRequest(referrer, null);
     }
 
-    @Test public void testValidRequest() {
+    @Test
+    public void testValidRequest() {
         Assert.assertEquals(false, filter.isValidRequest(getRequest(null)));
         Assert.assertEquals(true, filter.isValidRequest(getRequest("relative")));
         Assert.assertEquals(true, filter.isValidRequest(getRequest("/relative/too")));
@@ -105,7 +134,8 @@ public class ReferrerFilterTest {
         Assert.assertEquals(false, filter.isValidRequest(getRequest("http://yet.another.abshost:80")));
     }
 
-    @Test public void testIsBrowserRequest() {
+    @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)";

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.