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:46 UTC
[sling-org-apache-sling-security] 08/20: SLING-2141 : Update
localhost and server handling
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 2989f952235cf82cd03bddc03e72f7a93278dcfd
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Wed Aug 3 07:49:44 2011 +0000
SLING-2141 : Update localhost and server handling
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/security@1153377 13f79535-47bb-0310-9956-ffa450edef68
---
.../apache/sling/security/impl/ReferrerFilter.java | 200 ++++++++++++++++-----
.../OSGI-INF/metatype/metatype.properties | 8 +-
.../sling/security/impl/ReferrerFilterTest.java | 33 ++--
3 files changed, 172 insertions(+), 69 deletions(-)
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 b27ec45..9339900 100644
--- a/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java
+++ b/src/main/java/org/apache/sling/security/impl/ReferrerFilter.java
@@ -17,6 +17,18 @@
package org.apache.sling.security.impl;
import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@@ -45,56 +57,144 @@ public class ReferrerFilter implements Filter {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/** Default value for allow empty. */
- private static final boolean DEFAULT_ALLOW_EMPTY = true;
+ 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";
- /** Default value for allow localhost. */
- private static final boolean DEFAULT_ALLOW_LOCALHOST = true;
-
- /** Allow localhost property. */
- @Property(boolValue=DEFAULT_ALLOW_LOCALHOST)
- private static final String PROP_ALLOW_LOCALHOST = "allow.localhost";
-
/** Allow empty property. */
@Property(unbounded=PropertyUnbounded.ARRAY)
private static final String PROP_HOSTS = "allow.hosts";
+ /** Allow empty property. */
+ @Property(unbounded=PropertyUnbounded.ARRAY, value={"POST", "PUT", "DELETE"})
+ private static final String PROP_METHODS = "filter.methods";
+
/** Do we allow empty referrer? */
private boolean allowEmpty;
- /** Do we allow localhost referrer? */
- private boolean allowLocalhost;
+ /** Allowed referrers */
+ private URL[] allowedReferrers;
- /** Allowed hosts */
- private String[] allowHosts;
+ /** Methods to be filtered. */
+ private String[] filterMethods;
+
+ /**
+ * Create a default list of referrers
+ */
+ private Set<String> getDefaultAllowedReferrers() {
+ final Set<String> referrers = new HashSet<String>();
+ try {
+ final Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
+
+ while(ifaces.hasMoreElements()){
+ final NetworkInterface iface = ifaces.nextElement();
+ logger.info("Adding Allowed referers for Interface:" + iface.getDisplayName());
+ final Enumeration<InetAddress> ias = iface.getInetAddresses();
+ while(ias.hasMoreElements()){
+ final InetAddress ia = ias.nextElement();
+ final String address = ia.getHostAddress().trim().toLowerCase();
+ final String name = ia.getHostName().trim().toLowerCase();
+ if ( ia instanceof Inet4Address ) {
+ referrers.add("http://" + address + ":0");
+ referrers.add("https://" + address + ":0");
+ referrers.add("http://" + name + ":0");
+ referrers.add("https://" + name + ":0");
+ if (name.indexOf('.')>-1){
+ int index = name.indexOf('.');
+ String host = name.substring(0, index);
+ referrers.add("http://" + host.trim().toLowerCase() + ":0");
+ referrers.add("https://" + host.trim().toLowerCase() + ":0");
+ }
+ }
+ if ( ia instanceof Inet6Address ) {
+ referrers.add("http://[" + address + "]" + ":0");
+ referrers.add("https://[" + address + "]" + ":0");
+ referrers.add("http://[" + name + "]" + ":0");
+ referrers.add("https://[" + name + "]" + ":0");
+ }
+ }
+ }
+ } catch ( final SocketException se) {
+ logger.error("Unable to detect network interfaces", se);
+ }
+ referrers.add("http://localhost" + ":0");
+ referrers.add("http://127.0.0.1" + ":0");
+ referrers.add("http://[::1]" + ":0");
+ referrers.add("https://localhost" + ":0");
+ referrers.add("https://127.0.0.1" + ":0");
+ referrers.add("https://[::1]" + ":0");
+ return referrers;
+ }
+
+ private void add(final List<URL> urls, final String ref) {
+ try {
+ final URL u = new URL(ref);
+ urls.add(u);
+ } catch (final MalformedURLException mue) {
+ logger.warn("Unable to create URL from " + ref + " : " + mue.getMessage());
+ }
+ }
+
+ /**
+ * Create URLs out of the referrer list
+ */
+ private URL[] createReferrerUrls(final Set<String> referrers) {
+ final List<URL> urls = new ArrayList<URL>();
+
+ for(final String ref : referrers) {
+ final int pos = ref.indexOf("://");
+ // valid url?
+ if ( pos != -1 ) {
+ this.add(urls, ref);
+ } else {
+ this.add(urls, "http://" + ref + ":0");
+ this.add(urls, "https://" + ref + ":0");
+ }
+ }
+ return urls.toArray(new URL[urls.size()]);
+ }
/**
* Activate
*/
protected void activate(final ComponentContext ctx) {
this.allowEmpty = OsgiUtil.toBoolean(ctx.getProperties().get(PROP_ALLOW_EMPTY), DEFAULT_ALLOW_EMPTY);
- this.allowHosts = OsgiUtil.toStringArray(ctx.getProperties().get(PROP_HOSTS));
- this.allowLocalhost = OsgiUtil.toBoolean(ctx.getProperties().get(PROP_ALLOW_LOCALHOST), DEFAULT_ALLOW_LOCALHOST);
- if ( this.allowHosts != null ) {
- if ( this.allowHosts.length == 0 ) {
- this.allowHosts = null;
- } else if ( this.allowHosts.length == 1 && this.allowHosts[0].trim().length() == 0 ) {
- this.allowHosts = null;
+ String[] allowHosts = OsgiUtil.toStringArray(ctx.getProperties().get(PROP_HOSTS));
+ if ( allowHosts != null ) {
+ if ( allowHosts.length == 0 ) {
+ allowHosts = null;
+ } else if ( allowHosts.length == 1 && allowHosts[0].trim().length() == 0 ) {
+ allowHosts = null;
+ }
+ }
+ final Set<String> allowedReferrers = this.getDefaultAllowedReferrers();
+ if ( allowHosts != null ) {
+ for(final String host : allowHosts) {
+ allowedReferrers.add(host);
+ }
+ }
+ this.allowedReferrers = this.createReferrerUrls(allowedReferrers);
+ this.filterMethods = OsgiUtil.toStringArray(ctx.getProperties().get(PROP_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 ) {
+ for(int i=0; i<filterMethods.length; i++) {
+ filterMethods[i] = filterMethods[i].toUpperCase();
}
}
}
private boolean isModification(final HttpServletRequest req) {
final String method = req.getMethod();
- if ("POST".equals(method)) {
- return true;
- } else if ("PUT".equals(method)) {
- return true;
- } else if ("DELETE".equals(method)) {
- return true;
+ if ( filterMethods != null ) {
+ for(final String m : filterMethods) {
+ if ( m.equals(method) ) {
+ return true;
+ }
+ }
}
return false;
}
@@ -119,12 +219,21 @@ public class ReferrerFilter implements Filter {
chain.doFilter(req, res);
}
- String getHost(final String referrer) {
+ final static class HostInfo {
+ public String host;
+ public String scheme;
+ public int port;
+ }
+
+ HostInfo getHost(final String referrer) {
final int startPos = referrer.indexOf("://") + 3;
if ( startPos == 2 ) {
// we consider this illegal
return null;
}
+ final HostInfo info = new HostInfo();
+ info.scheme = referrer.substring(0, startPos - 3);
+
final int paramStart = referrer.indexOf('?');
final String hostAndPath = (paramStart == -1 ? referrer : referrer.substring(0, paramStart));
final int endPos = hostAndPath.indexOf('/', startPos);
@@ -132,9 +241,17 @@ public class ReferrerFilter implements Filter {
final int hostNameStart = hostPart.indexOf('@') + 1;
final int hostNameEnd = hostPart.lastIndexOf(':');
if (hostNameEnd < hostNameStart ) {
- return hostPart.substring(hostNameStart);
+ info.host = hostPart.substring(hostNameStart);
+ if ( info.scheme.equals("http") ) {
+ info.port = 80;
+ } else if ( info.scheme.equals("https") ) {
+ info.port = 443;
+ }
+ } else {
+ info.host = hostPart.substring(hostNameStart, hostNameEnd);
+ info.port = Integer.valueOf(hostPart.substring(hostNameEnd + 1));
}
- return hostPart.substring(hostNameStart, hostNameEnd);
+ return info;
}
boolean isValidRequest(final HttpServletRequest request) {
@@ -151,33 +268,22 @@ public class ReferrerFilter implements Filter {
return true;
}
- final String host = getHost(referrer);
- if ( host == null ) {
+ final HostInfo info = getHost(referrer);
+ if ( info == 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 boolean valid;
- boolean isValidLocalHost = false;
- if ( this.allowLocalhost ) {
- if ( "localhost".equals(host) || "127.0.0.1".equals(host) ) {
- isValidLocalHost = true;
- }
- }
- if ( isValidLocalHost ) {
- valid = true;
- } else if ( this.allowHosts == null ) {
- valid = host.equals(request.getServerName());
- } else {
- boolean flag = false;
- for(final String allowHost : this.allowHosts) {
- if ( host.equals(allowHost) ) {
- flag = true;
+
+ boolean valid = false;
+ for(final URL ref : this.allowedReferrers) {
+ if ( info.host.equals(ref.getHost()) && info.scheme.equals(ref.getProtocol()) ) {
+ if ( ref.getPort() == 0 || info.port == ref.getPort() ) {
+ valid = true;
break;
}
}
- valid = flag;
}
if ( !valid) {
this.logger.info("Rejected referrer header for {} request to {} : {}",
diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties
index 72ac2f5..f536075 100644
--- a/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ b/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -31,8 +31,8 @@ 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. If this is empty only the server\
- host is allowed. If this is set, it must include the server host name!
+allow.hosts.description = List of allowed hosts for the referrer. If this is empty only the default\
+ hosts are allowed.
-allow.localhost.name = Allow Localhost
-allow.localhost.description = If this is enabled, 'localhost' and '127.0.0.1' are always allowed.
\ No newline at end of file
+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 cd41e10..f892a97 100644
--- a/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java
+++ b/src/test/java/org/apache/sling/security/impl/ReferrerFilterTest.java
@@ -42,20 +42,20 @@ public class ReferrerFilterTest {
}
@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/somewhere?invald=@gagga"));
- 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("localhost", filter.getHost("http://localhost"));
- Assert.assertEquals("127.0.0.1", filter.getHost("http://127.0.0.1"));
- Assert.assertEquals("localhost", filter.getHost("http://localhost:535"));
- Assert.assertEquals("127.0.0.1", filter.getHost("http://127.0.0.1:242"));
- Assert.assertEquals("localhost", filter.getHost("http://localhost:256235/etewteq.ff"));
- Assert.assertEquals("127.0.0.1", filter.getHost("http://127.0.0.1/wetew.qerq"));
+ 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);
+ Assert.assertEquals("somehost", filter.getHost("http://admin@somehost/somewhere").host);
+ Assert.assertEquals("somehost", filter.getHost("http://admin@somehost/somewhere?invald=@gagga").host);
+ Assert.assertEquals("somehost", filter.getHost("http://admin@somehost:1/somewhere").host);
+ Assert.assertEquals("somehost", filter.getHost("http://admin:admin@somehost/somewhere").host);
+ Assert.assertEquals("somehost", filter.getHost("http://admin:admin@somehost:4343/somewhere").host);
+ Assert.assertEquals("localhost", filter.getHost("http://localhost").host);
+ Assert.assertEquals("127.0.0.1", filter.getHost("http://127.0.0.1").host);
+ Assert.assertEquals("localhost", filter.getHost("http://localhost:535").host);
+ Assert.assertEquals("127.0.0.1", filter.getHost("http://127.0.0.1:242").host);
+ Assert.assertEquals("localhost", filter.getHost("http://localhost:256235/etewteq.ff").host);
+ Assert.assertEquals("127.0.0.1", filter.getHost("http://127.0.0.1/wetew.qerq").host);
Assert.assertEquals(null, filter.getHost("http:/admin:admin@somehost:4343/somewhere"));
}
@@ -64,20 +64,17 @@ public class ReferrerFilterTest {
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(false, 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(true, filter.isValidRequest(getRequest("http://localhost")));
Assert.assertEquals(true, filter.isValidRequest(getRequest("http://127.0.0.1")));
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>.