You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by rb...@apache.org on 2013/05/10 16:32:53 UTC
svn commit: r1481027 - in /shindig/trunk: config/ java/common/conf/
java/gadgets/src/main/java/org/apache/shindig/gadgets/
java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/
java/gadgets/src/test/java/org/apache/shindig/gadgets/render/
Author: rbaxter85
Date: Fri May 10 14:32:52 2013
New Revision: 1481027
URL: http://svn.apache.org/r1481027
Log:
Implement referer checks for shindig endpoints
SHINDIG-1858
Committed For Zhi Hong Yang
Modified:
shindig/trunk/config/container.js
shindig/trunk/java/common/conf/shindig.properties
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractLockedDomainService.java
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetContext.java
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/HashLockedDomainService.java
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/LockedDomainService.java
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpGadgetContext.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java
Modified: shindig/trunk/config/container.js
URL: http://svn.apache.org/viewvc/shindig/trunk/config/container.js?rev=1481027&r1=1481026&r2=1481027&view=diff
==============================================================================
--- shindig/trunk/config/container.js (original)
+++ shindig/trunk/config/container.js Fri May 10 14:32:52 2013
@@ -120,6 +120,10 @@
// Should all gadgets be forced on to a locked domain?
"gadgets.uri.iframe.lockedDomainRequired" : false,
+// The permitted domain where the render request is sent from. For examle: ["www.hostA.com", "www.hostB.com"]
+// Empty means all domains are permitted.
+"shindig.locked-domain.permittedRefererDomains" : [],
+
// Default Js Uri config: also must be overridden.
// gadgets.uri.js.host should be protocol relative.
"gadgets.uri.js.host" : "//${Cur['default.domain.unlocked.server']}", // Use unlocked host for better caching.
@@ -336,4 +340,5 @@
// This variable is needed during the container feature init.
"jsPath" : "${Cur['gadgets.uri.js.path']}"
}
-}}
+}
+}
Modified: shindig/trunk/java/common/conf/shindig.properties
URL: http://svn.apache.org/viewvc/shindig/trunk/java/common/conf/shindig.properties?rev=1481027&r1=1481026&r2=1481027&view=diff
==============================================================================
--- shindig/trunk/java/common/conf/shindig.properties (original)
+++ shindig/trunk/java/common/conf/shindig.properties Fri May 10 14:32:52 2013
@@ -59,6 +59,9 @@ shindig.signing.viewer-access-tokens-ena
# If enabled here, configuration values can be found in container configuration files.
shindig.locked-domain.enabled=false
+# Enable or disable referrer check.
+shindig.locked-domain.refererCheck.enabled=false
+
# TODO: This needs to be moved to container configuration.
shindig.content-rewrite.only-allow-excludes=false
shindig.content-rewrite.include-urls=.*
Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractLockedDomainService.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractLockedDomainService.java?rev=1481027&r1=1481026&r2=1481027&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractLockedDomainService.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractLockedDomainService.java Fri May 10 14:32:52 2013
@@ -18,9 +18,15 @@
*/
package org.apache.shindig.gadgets;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.shindig.common.logging.i18n.MessageKeys;
import org.apache.shindig.config.ContainerConfig;
import com.google.common.collect.Maps;
@@ -52,23 +58,34 @@ public abstract class AbstractLockedDoma
Collection<String> removed) {
for (String container : changed) {
required.put(container, config.getBool(container, LOCKED_DOMAIN_REQUIRED_KEY));
+ permittedRefererDomains.put(container, config.getList(container, PERMITTED_REFERER_DOMAINS_KEY));
}
for (String container : removed) {
required.remove(container);
+ permittedRefererDomains.remove(container);
}
}
}
protected static final String LOCKED_DOMAIN_REQUIRED_KEY = "gadgets.uri.iframe.lockedDomainRequired";
+ protected static final String PERMITTED_REFERER_DOMAINS_KEY = "shindig.locked-domain.permittedRefererDomains";
+
protected static final String LOCKED_DOMAIN_FEATURE = "locked-domain";
private final boolean enabled;
+ private boolean refererCheckEnabled;
+
protected final Map<String, Boolean> required;
private boolean lockSecurityTokens = false;
private LockedDomainObserver ldObserver;
+ protected final Map<String, List<Object>> permittedRefererDomains;
+
+ private static final String classname = HashLockedDomainService.class.getName();
+ private static final Logger LOG = Logger.getLogger(classname, MessageKeys.MESSAGES);
+
/**
* Create a LockedDomainService. This constructor should be called by implementors.
*
@@ -80,12 +97,18 @@ public abstract class AbstractLockedDoma
protected AbstractLockedDomainService(ContainerConfig config, boolean enabled) {
this.enabled = enabled;
this.required = Maps.newHashMap();
+ this.permittedRefererDomains = Maps.newHashMap();
if (enabled) {
this.ldObserver = new LockedDomainObserver();
config.addConfigObserver(this.ldObserver, true);
}
}
+ @Inject
+ public void setRefererCheckEnabled(@Named("shindig.locked-domain.refererCheck.enabled") boolean refererCheckEnabled) {
+ this.refererCheckEnabled = refererCheckEnabled;
+ }
+
/*
* (non-Javadoc)
*
@@ -131,6 +154,15 @@ public abstract class AbstractLockedDoma
return true;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.shindig.gadgets.LockedDomainService#isRefererCheckEnabled()
+ */
+ public boolean isRefererCheckEnabled() {
+ return this.refererCheckEnabled;
+ }
+
/**
* Allows a renderer to render all gadgets that require a security token on a locked domain. This
* is recommended security practice, as it secures the token from other gadgets, but because the
@@ -150,11 +182,11 @@ public abstract class AbstractLockedDoma
}
/**
- * Returns true iff domain locking is enforced for every gadget by the container
+ * Returns true if domain locking is enforced for every gadget by the container
*
* @param container
* the container configuration, e.g., "default"
- * @return true iff domain locking is enforced by the container
+ * @return true if domain locking is enforced by the container
*/
protected boolean isDomainLockingEnforced(String container) {
return this.required.get(container);
@@ -169,14 +201,14 @@ public abstract class AbstractLockedDoma
}
/**
- * Returns true iff the gadget is requesting to be on a locked domain. If security token locking
+ * Returns true if the gadget is requesting to be on a locked domain. If security token locking
* has been enabled via {@link #setLockSecurityTokens(Boolean)}, this method will return true if
* the gadget is explicitly or implicitly requesting locked domains; otherwise, this will return
* true only if the gadget is explicitly requesting locked domains.
*
* @param gadget
* the gadget
- * @return true iff the gadget is requesting to be on a locked domain
+ * @return true if the gadget is requesting to be on a locked domain
*/
protected boolean isGadgetReqestingLocking(Gadget gadget) {
if (this.lockSecurityTokens) {
@@ -184,4 +216,48 @@ public abstract class AbstractLockedDoma
}
return gadget.getViewFeatures().keySet().contains(LOCKED_DOMAIN_FEATURE);
}
+
+ /**
+ * Check whether the referer value in the request head is in the permitted referer domain list or not.
+ * @param gadget
+ * the gadget
+ * @param container
+ * the container
+ * @return true if the referer is valid, otherwise return false.
+ */
+ protected boolean isValidReferer(Gadget gadget, String container) {
+ String referer = gadget.getContext().getReferer();
+ List<Object> domainList = this.permittedRefererDomains.get(container);
+ if (null != referer && !"".equals(referer.trim())) {
+ try {
+ URL url = new URL(referer);
+ if (!domainList.isEmpty()) {
+ boolean matched = false;
+ String refererHost = url.getHost().toLowerCase();
+ for (Object permittedDomain: domainList) {
+ if (refererHost.endsWith(((String) permittedDomain).toLowerCase())) {
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) {
+ LOG.logp(Level.SEVERE, classname, "Referer check failed.",
+ MessageKeys.FAILED_TO_VALIDATE, new Object[] { referer });
+ return false;
+ }
+ }
+ } catch (MalformedURLException e) {
+ LOG.logp(Level.SEVERE, classname, "Referer check failed, malformed referer url.",
+ MessageKeys.FAILED_TO_VALIDATE, new Object[] { referer });
+ return false;
+ }
+ } else {
+ if (!domainList.isEmpty()) {
+ LOG.logp(Level.SEVERE, classname, "Referer check failed, referer url is not valid.",
+ MessageKeys.FAILED_TO_VALIDATE, new Object[] { referer });
+ return false;
+ }
+ }
+ return true;
+ }
}
Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetContext.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetContext.java?rev=1481027&r1=1481026&r2=1481027&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetContext.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetContext.java Fri May 10 14:32:52 2013
@@ -168,5 +168,9 @@ public class GadgetContext {
public String getRepository() {
return delegate == null ? null : delegate.getRepository();
}
+
+ public String getReferer() {
+ return delegate == null ? null : delegate.getReferer();
+ }
}
Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/HashLockedDomainService.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/HashLockedDomainService.java?rev=1481027&r1=1481026&r2=1481027&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/HashLockedDomainService.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/HashLockedDomainService.java Fri May 10 14:32:52 2013
@@ -147,6 +147,9 @@ public class HashLockedDomainService ext
if (isEnabled()) {
if (isGadgetReqestingLocking(gadget) || isHostUsingLockedDomain(host)
|| isDomainLockingEnforced(container)) {
+ if (isRefererCheckEnabled() && !isValidReferer(gadget, container)) {
+ return false;
+ }
String neededHost;
try {
neededHost = getLockedDomain(gadget, container);
Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/LockedDomainService.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/LockedDomainService.java?rev=1481027&r1=1481026&r2=1481027&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/LockedDomainService.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/LockedDomainService.java Fri May 10 14:32:52 2013
@@ -71,4 +71,9 @@ public interface LockedDomainService {
* Returns false if locked domains are not enabled on the server.
*/
boolean isHostUsingLockedDomain(String host);
+
+ /**
+ * @return If referrer check is enabled, return true. Otherwise, return false.
+ */
+ boolean isRefererCheckEnabled();
}
Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpGadgetContext.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpGadgetContext.java?rev=1481027&r1=1481026&r2=1481027&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpGadgetContext.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpGadgetContext.java Fri May 10 14:32:52 2013
@@ -51,6 +51,7 @@ public class HttpGadgetContext extends G
private final Uri url;
private final UserPrefs userPrefs;
private final String view;
+ private final String referer;
public HttpGadgetContext(HttpServletRequest request) {
this.request = request;
@@ -64,6 +65,7 @@ public class HttpGadgetContext extends G
url = getUrl(request);
userPrefs = getUserPrefs(request);
view = getView(request);
+ referer = getReferer();
}
@Override
@@ -166,6 +168,12 @@ public class HttpGadgetContext extends G
return repository;
}
+ @Override
+ public String getReferer() {
+ String referer = request.getHeader("Referer");
+ return referer == null ? super.getReferer() : referer;
+ }
+
/**
* @param req
* @return The container, if set, or null.
Modified: shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java?rev=1481027&r1=1481026&r2=1481027&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java (original)
+++ shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java Fri May 10 14:32:52 2013
@@ -295,5 +295,9 @@ public class RendererTest {
public boolean isHostUsingLockedDomain(String host) {
return false;
}
+
+ public boolean isRefererCheckEnabled() {
+ return false;
+ }
}
}