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:12:42 UTC

[sling-org-apache-sling-security] 04/20: SLING-2141 - Add a way to check the referrer for modification requests

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.security-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-security.git

commit ac5acb361b4b53b2140436695459a4a6ef11f704
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Fri Jul 15 06:07:54 2011 +0000

    SLING-2141 - Add a way to check the referrer for modification requests
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/security@1146968 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            | 14 ++++
 .../apache/sling/security/impl/ReferrerFilter.java | 55 ++++++++++------
 .../sling/security/impl/ReferrerFilterTest.java    | 74 ++++++++++++++++++++++
 3 files changed, 124 insertions(+), 19 deletions(-)

diff --git a/pom.xml b/pom.xml
index 84adade..2c9ef01 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,5 +94,19 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.8.2</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
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 9c0cae2..ed3dec5 100644
--- a/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java
+++ b/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java
@@ -1,19 +1,22 @@
 /*
- * Copyright 1997-2011 Day Management AG
- * Barfuesserplatz 6, 4001 Basel, Switzerland
- * All Rights Reserved.
+ * 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
  *
- * This software is the confidential and proprietary information of
- * Day Management AG, ("Confidential Information"). You shall not
- * disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Day.
+ *      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.
  */
 package org.apache.sling.security.impl;
 
 import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
@@ -38,6 +41,9 @@ import org.slf4j.LoggerFactory;
         label="%referrer.name")
 public class ReferrerFilter implements Filter {
 
+    /** Logger. */
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
     private static final boolean DEFAULT_ALLOW_EMPTY = true;
 
     @Property(boolValue=DEFAULT_ALLOW_EMPTY)
@@ -65,9 +71,6 @@ public class ReferrerFilter implements Filter {
         }
     }
 
-    /** Logger. */
-    private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
     private boolean isModification(final HttpServletRequest req) {
         final String method = req.getMethod();
         if ("POST".equals(method)) {
@@ -100,7 +103,23 @@ public class ReferrerFilter implements Filter {
         chain.doFilter(req, res);
     }
 
-    private boolean isValidRequest(final HttpServletRequest request) {
+    String getHost(final String referrer) {
+        final int startPos = referrer.indexOf("://") + 3;
+        if ( startPos == 2 ) {
+            // we consider this illegal
+            return null;
+        }
+        final int endPos = referrer.indexOf('/', startPos);
+        final String hostPart = (endPos == -1 ? referrer.substring(startPos) : referrer.substring(startPos, endPos));
+        final int hostNameStart = hostPart.indexOf('@') + 1;
+        final int hostNameEnd = hostPart.lastIndexOf(':');
+        if (hostNameEnd < hostNameStart ) {
+            return hostPart.substring(hostNameStart);
+        }
+        return hostPart.substring(hostNameStart, hostNameEnd);
+    }
+
+    boolean isValidRequest(final HttpServletRequest request) {
         final String referrer = request.getHeader("referer");
         // check for missing/empty referrer
         if ( referrer == null || referrer.trim().length() == 0 ) {
@@ -113,16 +132,14 @@ public class ReferrerFilter implements Filter {
         if ( referrer.indexOf(":/") == - 1 ) {
             return true;
         }
-        final URI uri;
-        try {
-            uri = new URI(referrer);
-        } catch (URISyntaxException e) {
+
+        final String host = getHost(referrer);
+        if ( host == null ) {
             // if this is invalid we just return invalid
             this.logger.info("Rejected illegal referrer header for {} request to {} : {}",
                     new Object[] {request.getMethod(), request.getRequestURI(), referrer});
             return false;
         }
-        final String host = uri.getHost();
         final boolean valid;
         if ( this.allowHosts == null ) {
             valid = host.equals(request.getServerName());
diff --git a/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java b/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java
new file mode 100644
index 0000000..f6264c1
--- /dev/null
+++ b/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+package org.apache.sling.security.impl;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.service.component.ComponentContext;
+
+public class ReferrerFilterTest {
+
+    protected ReferrerFilter filter;
+
+    @Before public void setup() {
+        filter = new ReferrerFilter();
+        final ComponentContext ctx = mock(ComponentContext.class);
+        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        when(ctx.getProperties()).thenReturn(props);
+        filter.activate(ctx);
+    }
+
+    @Test public void testHostName() {
+        Assert.assertEquals("somehost", filter.getHost("http://somehost"));
+        Assert.assertEquals("somehost", filter.getHost("http://somehost/somewhere"));
+        Assert.assertEquals("somehost", filter.getHost("http://somehost:4242/somewhere"));
+        Assert.assertEquals("somehost", filter.getHost("http://admin@somehost/somewhere"));
+        Assert.assertEquals("somehost", filter.getHost("http://admin@somehost:1/somewhere"));
+        Assert.assertEquals("somehost", filter.getHost("http://admin:admin@somehost/somewhere"));
+        Assert.assertEquals("somehost", filter.getHost("http://admin:admin@somehost:4343/somewhere"));
+        Assert.assertEquals(null, filter.getHost("http:/admin:admin@somehost:4343/somewhere"));
+    }
+
+    private HttpServletRequest getRequest(final String referrer) {
+        final HttpServletRequest request = mock(HttpServletRequest.class);
+        when(request.getMethod()).thenReturn("POST");
+        when(request.getRequestURI()).thenReturn("http://somehost/somewhere");
+        when(request.getHeader("referer")).thenReturn(referrer);
+        when(request.getServerName()).thenReturn("me");
+        return request;
+    }
+
+    @Test public void testValidRequest() {
+        Assert.assertEquals(true, filter.isValidRequest(getRequest(null)));
+        Assert.assertEquals(true, filter.isValidRequest(getRequest("relative")));
+        Assert.assertEquals(true, filter.isValidRequest(getRequest("/relative/too")));
+        Assert.assertEquals(true, filter.isValidRequest(getRequest("/relative/but/[illegal]")));
+        Assert.assertEquals(false, filter.isValidRequest(getRequest("http://somehost")));
+        Assert.assertEquals(true, filter.isValidRequest(getRequest("http://me")));
+        Assert.assertEquals(false, filter.isValidRequest(getRequest("http://somehost/but/[illegal]")));
+        Assert.assertEquals(true, filter.isValidRequest(getRequest("http://me/but/[illegal]")));
+    }
+}

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