[gatein-commits] gatein SVN: r5184 - in portal/trunk: component/web/security/src/main/java/org/exoplatform/web/security/proxy and 3 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Fri Nov 19 12:45:50 EST 2010


Author: julien_viet
Date: 2010-11-19 12:45:49 -0500 (Fri, 19 Nov 2010)
New Revision: 5184

Added:
   portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/proxy/
   portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/proxy/ProxyFilterService.java
   portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ProxyServletFilter.java
Modified:
   portal/trunk/gadgets/server/src/main/webapp/WEB-INF/web.xml
   portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/common/common-configuration.xml
Log:
GTNPORTAL-1647 : Domain based gadget proxy filtering


Added: portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/proxy/ProxyFilterService.java
===================================================================
--- portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/proxy/ProxyFilterService.java	                        (rev 0)
+++ portal/trunk/component/web/security/src/main/java/org/exoplatform/web/security/proxy/ProxyFilterService.java	2010-11-19 17:45:49 UTC (rev 5184)
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.web.security.proxy;
+
+import org.exoplatform.container.PortalContainer;
+import org.exoplatform.container.xml.InitParams;
+import org.exoplatform.container.xml.ValuesParam;
+import org.gatein.common.logging.Logger;
+import org.gatein.common.logging.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * The proxy filter service is used for filtering http access when it is performed by GateIn.
+ * The following rules applies to the filtering:
+ *
+ * <ul>
+ * <li>Same host URI grants access</li>
+ * <li>A black list match of the host denies access</li>
+ * <li>A white list match of the host grants access</li>
+ * <li>Access is denied</li>
+ * </ul>
+ *
+ * The service is configured by
+ * <ul>
+ * <li>a <code>white-list</code> parameter that specifies a list of white list rules</li>
+ * <li>a <code>black-list</code> parameter that specifies a list of black list rules</li>
+ * </ul>
+ *
+ * Rules are trimmed and the wildcard character can be used to match any number of character.
+ *
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class ProxyFilterService
+{
+
+   /** . */
+   private static final Logger log = LoggerFactory.getLogger(ProxyFilterService.class);
+
+   /** . */
+   private final List<Pattern> whiteList;
+
+   /** . */
+   private final List<Pattern> blackList;
+
+   public ProxyFilterService(InitParams params)
+   {
+      this.whiteList = createList(params.getValuesParam("white-list"));
+      this.blackList = createList(params.getValuesParam("black-list"));
+
+      // A bit of logging
+      log.debug("Proxy filter service white list " + whiteList);
+      log.debug("Proxy filter service black list " + blackList);
+   }
+
+   private List<Pattern> createList(ValuesParam values)
+   {
+      if (values != null)
+      {
+         ArrayList<Pattern> patterns = new ArrayList<Pattern>();
+         for (Object value : values.getValues())
+         {
+            String s = ((String)value).trim();
+            StringBuilder sb = new StringBuilder("^");
+            for (int i = 0;i < s.length();i++)
+            {
+               char c = s.charAt(i);
+               switch (c)
+               {
+                  case '*':
+                     sb.append(".*");
+                     break;
+                  case '[':
+                  case '\\':
+                  case '^':
+                  case '$':
+                  case '.':
+                  case '|':
+                  case '?':
+                  case '+':
+                  case '(':
+                  case ')':
+                     sb.append("\\");
+                     sb.append(c);
+                     break;
+                  default:
+                     sb.append(c);
+                     break;
+               }
+            }
+            sb.append("$");
+            Pattern pattern = Pattern.compile(sb.toString());
+            patterns.add(pattern);
+         }
+         return Collections.unmodifiableList(patterns);
+      }
+      else
+      {
+         return Collections.emptyList();
+      }
+   }
+
+   /**
+    * Returns true if access to a remote URI should be granted.
+    *
+    * @param request the servlet request doing the request
+    * @param container the portal container associated with the request
+    * @param remoteURI the remote URI to check
+    * @return the access to the remote URI
+    */
+   public boolean accept(
+      HttpServletRequest request,
+      PortalContainer container,
+      URI remoteURI)
+   {
+      boolean trace = log.isTraceEnabled();
+
+      //
+      String remoteHost = remoteURI.getHost();
+
+      // Filter based on same server name
+      String remoteServerName = request.getServerName();
+      if (remoteHost.equals(remoteServerName))
+      {
+         if (trace)
+         {
+            log.trace("Same host matching for URI " + remoteURI);
+         }
+         return true;
+      }
+
+      // Otherwise go through black list first
+      for (int i = 0;i < blackList.size();i++)
+      {
+         Pattern pattern = blackList.get(i);
+         boolean rejected = pattern.matcher(remoteHost).matches();
+         if (trace)
+         {
+            log.trace("Black list " +  pattern + (rejected ? " matched URI " : " did not match URI") + remoteURI);
+         }
+         if (rejected)
+         {
+            return false;
+         }
+      }
+
+      // Finally go through white list first
+      for (int i = 0;i < whiteList.size();i++)
+      {
+         Pattern pattern = whiteList.get(i);
+         boolean accepted = pattern.matcher(remoteHost).matches();
+         if (trace)
+         {
+            log.trace("White list " +  pattern + (accepted ? " matched URI " : " did not match URI") + remoteURI);
+         }
+         if (accepted)
+         {
+            return true;
+         }
+      }
+
+      //
+      if (trace)
+      {
+         log.trace("Rejected implicitely uri " + remoteURI);
+      }
+
+      //
+      return false;
+   }
+}

Added: portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ProxyServletFilter.java
===================================================================
--- portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ProxyServletFilter.java	                        (rev 0)
+++ portal/trunk/gadgets/core/src/main/java/org/exoplatform/portal/gadget/core/ProxyServletFilter.java	2010-11-19 17:45:49 UTC (rev 5184)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2010 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.portal.gadget.core;
+
+import org.exoplatform.container.PortalContainer;
+import org.exoplatform.web.security.proxy.ProxyFilterService;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * The proxy servlet filter is a servlet filter placed in front of Shindig proxy servlet.
+ * It filters a request and allows only the request satisfying the following:
+ * <ul>
+ * <li>the request has an URL parameter</li>
+ * <li>the request can locate a container associated with the request</li>
+ * <li>the request can locate the {@link ProxyFilterService} within the container</li>
+ * <li>the method {@link ProxyFilterService#accept(HttpServletRequest, PortalContainer, URI)} invocation returns true</li>
+ * </ul>
+ *
+ * This service is located in front and does not use Shindig integration point (such as org.apache.shindig.gadgets.GadgetBlacklist}
+ * as the execution is performed by a thread that is not associated with the portal request precluding any access to
+ * information enabling contextual filtering.
+ *
+ * @author <a href="mailto:julien.viet at exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+public class ProxyServletFilter implements Filter
+{
+
+   /** . */
+   private ServletContext ctx;
+
+   public void init(FilterConfig cfg) throws ServletException
+   {
+      this.ctx = cfg.getServletContext();
+   }
+
+   public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException
+   {
+      HttpServletRequest hreq = (HttpServletRequest)req;
+      HttpServletResponse hresp = (HttpServletResponse)resp;
+
+      // Get URL
+      String url = hreq.getParameter("url");
+      if (url == null)
+      {
+         hresp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "No URL");
+      }
+      else
+      {
+         // Get container
+         PortalContainer container = PortalContainer.getInstance(ctx);
+         if (container == null)
+         {
+            hresp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Could not access container for servlet context " + ctx.getContextPath());
+         }
+         else
+         {
+            ProxyFilterService service = (ProxyFilterService)container.getComponentInstanceOfType(ProxyFilterService.class);
+            if (service == null)
+            {
+               hresp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Could not access proxy filter service " + ctx.getContextPath());
+            }
+            else
+            {
+               URI uri = URI.create(url);
+               if (!service.accept(hreq, container, uri))
+               {
+                  hresp.sendError(HttpServletResponse.SC_FORBIDDEN, "Gadget " + url + " is blacklisted");
+               }
+               else
+               {
+                  chain.doFilter(req, resp);
+               }
+            }
+         }
+      }
+   }
+
+   public void destroy()
+   {
+   }
+}

Modified: portal/trunk/gadgets/server/src/main/webapp/WEB-INF/web.xml
===================================================================
--- portal/trunk/gadgets/server/src/main/webapp/WEB-INF/web.xml	2010-11-19 17:29:02 UTC (rev 5183)
+++ portal/trunk/gadgets/server/src/main/webapp/WEB-INF/web.xml	2010-11-19 17:45:49 UTC (rev 5184)
@@ -26,6 +26,9 @@
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
          id="Shindig"
          version="2.5">
+
+  <display-name>eXoGadgetServer</display-name>
+
   <!-- configuration -->
   <!-- If you have your own Guice module(s), put them here as a colon-separated list. -->
   <context-param>
@@ -44,6 +47,11 @@
     <filter-name>authFilter</filter-name>
     <filter-class>org.apache.shindig.auth.AuthenticationServletFilter</filter-class>
   </filter>
+
+  <filter>
+    <filter-name>ProxyServletFilter</filter-name>
+    <filter-class>org.exoplatform.portal.gadget.core.ProxyServletFilter</filter-class>
+  </filter>
   
   <filter-mapping>
     <filter-name>authFilter</filter-name>
@@ -65,6 +73,11 @@
     <url-pattern>/gadgets/api/rpc/*</url-pattern>
   </filter-mapping>
 
+  <filter-mapping>
+    <filter-name>ProxyServletFilter</filter-name>
+    <servlet-name>proxy</servlet-name>
+  </filter-mapping>
+
   <listener>
     <listener-class>org.apache.shindig.common.servlet.GuiceServletContextListener</listener-class>
   </listener>

Modified: portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/common/common-configuration.xml
===================================================================
--- portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/common/common-configuration.xml	2010-11-19 17:29:02 UTC (rev 5183)
+++ portal/trunk/web/portal/src/main/webapp/WEB-INF/conf/common/common-configuration.xml	2010-11-19 17:45:49 UTC (rev 5184)
@@ -163,6 +163,23 @@
     <type>org.exoplatform.groovyscript.text.TemplateService</type>
   </component>
 
+  <component>
+  	<key>org.exoplatform.web.security.proxy.ProxyFilterService</key>
+  	<type>org.exoplatform.web.security.proxy.ProxyFilterService</type>
+    <init-params>
+      <values-param>
+        <!-- The white list -->
+        <name>white-list</name>
+        <!-- We accept anything not black listed -->
+        <value>*</value>
+      </values-param>
+      <values-param>
+        <name>black-list</name>
+        <value>*.evil.org</value>
+      </values-param>
+    </init-params>
+  </component>
+
   <external-component-plugins>
     <target-component>org.exoplatform.services.cache.ExoCacheFactory</target-component>
     <component-plugin>



More information about the gatein-commits mailing list