You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2012/07/24 10:08:51 UTC

svn commit: r1364930 - in /myfaces/tobago/trunk: tobago-core/src/main/java/org/apache/myfaces/tobago/config/ tobago-core/src/main/java/org/apache/myfaces/tobago/context/ tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/ tobago-core/s...

Author: lofwyr
Date: Tue Jul 24 08:08:50 2012
New Revision: 1364930

URL: http://svn.apache.org/viewvc?rev=1364930&view=rev
Log:
TOBAGO-1171: Support for the Content Security Policy (CSP) 
 - you can switch CSP on in the tobago-config.xml (please do that only for development in the moment)
 - support for different UserAgent (different header names)
 still open:
 - The renderers of Tobago must be refactored

Modified:
    myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java
    myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/context/UserAgent.java
    myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigBuilder.java
    myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigFragment.java
    myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigImpl.java
    myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParser.java
    myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseUtils.java
    myfaces/tobago/trunk/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.6.xsd
    myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/tobago-config.xml
    myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/PageRenderer.java

Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java?rev=1364930&r1=1364929&r2=1364930&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java Tue Jul 24 08:08:50 2012
@@ -76,4 +76,6 @@ public abstract class TobagoConfig {
 
   public abstract boolean isPreventFrameAttacks();
 
+  public abstract List<String> getContentSecurityPolicy();
+
 }

Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/context/UserAgent.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/context/UserAgent.java?rev=1364930&r1=1364929&r2=1364930&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/context/UserAgent.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/context/UserAgent.java Tue Jul 24 08:08:50 2012
@@ -33,7 +33,6 @@ public class UserAgent implements Serial
 
   public static final UserAgent DEFAULT = new UserAgent(null, null);
 
-
   public static final UserAgent MSIE = new UserAgent("msie", null);
 
   /**
@@ -65,7 +64,8 @@ public class UserAgent implements Serial
 
   public static final UserAgent MSIE_9_0 = new UserAgent("msie", "9_0", EnumSet.of(Capability.CONTENT_TYPE_XHTML));
 
-  public static final UserAgent MSIE_10_0 = new UserAgent("msie", "10_0", EnumSet.of(Capability.CONTENT_TYPE_XHTML));
+  public static final UserAgent MSIE_10_0
+      = new UserAgent("msie", "10_0", EnumSet.of(Capability.CONTENT_TYPE_XHTML), CspHeader.CSP_GECKO);
 
   /**
    * @deprecated no longer supported, since Tobago 1.5
@@ -151,19 +151,22 @@ public class UserAgent implements Serial
    * e. g. Firefox 4.0
    */
   public static final UserAgent GECKO_2_0
-      = new UserAgent("gecko", "2_0", EnumSet.of(Capability.PLACEHOLDER, Capability.CONTENT_TYPE_XHTML));
+      = new UserAgent("gecko", "2_0",
+      EnumSet.of(Capability.PLACEHOLDER, Capability.CONTENT_TYPE_XHTML), CspHeader.CSP_GECKO);
 
   /**
    * e. g. Firefox 5.0
    */
   public static final UserAgent GECKO_5_0
-      = new UserAgent("gecko", "5_0", EnumSet.of(Capability.PLACEHOLDER, Capability.CONTENT_TYPE_XHTML));
+      = new UserAgent("gecko", "5_0",
+      EnumSet.of(Capability.PLACEHOLDER, Capability.CONTENT_TYPE_XHTML), CspHeader.CSP_GECKO);
 
   /**
    * e. g. Safari 4, Safari 5, Chrome
    */
   public static final UserAgent WEBKIT
-      = new UserAgent("webkit", null, EnumSet.of(Capability.PLACEHOLDER, Capability.CONTENT_TYPE_XHTML));
+      = new UserAgent("webkit", null,
+      EnumSet.of(Capability.PLACEHOLDER, Capability.CONTENT_TYPE_XHTML), CspHeader.CSP_WEBKIT);
 
   private final String name;
 
@@ -171,14 +174,21 @@ public class UserAgent implements Serial
 
   private final EnumSet<Capability> capabilities;
 
+  private final CspHeader cspHeader;
+
   private UserAgent(String name, String version) {
-    this(name , version, EnumSet.of(Capability.CONTENT_TYPE_XHTML));
+    this(name, version, EnumSet.of(Capability.CONTENT_TYPE_XHTML), null);
   }
 
   private UserAgent(String name, String version, EnumSet<Capability> capabilities) {
+    this(name, version, capabilities, CspHeader.CSP_NOT_SUPPORTED);
+  }
+
+  private UserAgent(String name, String version, EnumSet<Capability> capabilities, CspHeader cspHeader) {
     this.name = name;
     this.version = version;
     this.capabilities = capabilities;
+    this.cspHeader = cspHeader;
   }
 
   public boolean hasCapability(Capability capability) {
@@ -220,6 +230,13 @@ public class UserAgent implements Serial
     return list;
   }
 
+  /**
+   * @return The HTTP header name for Content-Security-Policy.
+   */
+  public String getCspHeader() {
+    return cspHeader.getName();
+  }
+
   public static UserAgent getInstance(String header) {
     if (header == null) {
       return DEFAULT;
@@ -282,4 +299,22 @@ public class UserAgent implements Serial
         ? name + '_' + version
         : name;
   }
+
+  private static enum CspHeader {
+
+    CSP_NOT_SUPPORTED(null),
+    CSP_GECKO("X-Content-Security-Policy"),
+    CSP_WEBKIT("X-WebKit-CSP"),
+    CSP_STANDARD("Content-Security-Policy");
+
+    private String name;
+
+    private CspHeader(String name) {
+      this.name = name;
+    }
+
+    public String getName() {
+      return name;
+    }
+  }
 }

Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigBuilder.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigBuilder.java?rev=1364930&r1=1364929&r2=1364930&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigBuilder.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigBuilder.java Tue Jul 24 08:08:50 2012
@@ -122,6 +122,10 @@ public class TobagoConfigBuilder {
 
       result.setPreventFrameAttacks(fragment.isPreventFrameAttacks());
 
+      for(String directive : fragment.getContentSecurityPolicy()) {
+        result.addContentSecurityPolicy(directive);
+      }
+
       // theme definition
       // todo
 /*

Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigFragment.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigFragment.java?rev=1364930&r1=1364929&r2=1364930&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigFragment.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigFragment.java Tue Jul 24 08:08:50 2012
@@ -41,6 +41,7 @@ public class TobagoConfigFragment {
   private Boolean createSessionSecret;
   private Boolean checkSessionSecret;
   private boolean preventFrameAttacks = true;
+  private List<String> contentSecurityPolicy;
   // todo
   private List<ThemeImpl> themeDefinitions;
   private URL url;
@@ -51,6 +52,7 @@ public class TobagoConfigFragment {
     supportedThemeNames = new ArrayList<String>();
     resourceDirs = new ArrayList<String>();
     themeDefinitions = new ArrayList<ThemeImpl>();
+    contentSecurityPolicy = new ArrayList<String>();
   }
 
   public void addSupportedThemeName(String name) {
@@ -152,6 +154,14 @@ public class TobagoConfigFragment {
     this.preventFrameAttacks = preventFrameAttacks;
   }
 
+  public List<String> getContentSecurityPolicy() {
+    return contentSecurityPolicy;
+  }
+
+  public void addContentSecurityPolicy(String directive) {
+    contentSecurityPolicy.add(directive);
+  }
+
   /** @deprecated since 1.5.0 */
   @Deprecated
   public void setFixResourceOrder(String value) {

Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigImpl.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigImpl.java?rev=1364930&r1=1364929&r2=1364930&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigImpl.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigImpl.java Tue Jul 24 08:08:50 2012
@@ -57,6 +57,7 @@ public class TobagoConfigImpl extends To
   private boolean createSessionSecret;
   private boolean checkSessionSecret;
   private boolean preventFrameAttacks = true;
+  private List<String> contentSecurityPolicy;
   private URL url;
   private Map<String, String> defaultValidatorInfo;
 
@@ -66,6 +67,7 @@ public class TobagoConfigImpl extends To
     resourceDirs = new ArrayList<String>();
     createSessionSecret = true;
     checkSessionSecret = true;
+    contentSecurityPolicy = new ArrayList<String>();
   }
 
   public void addSupportedThemeName(String name) {
@@ -276,6 +278,14 @@ public class TobagoConfigImpl extends To
     this.preventFrameAttacks = preventFrameAttacks;
   }
 
+  public List<String> getContentSecurityPolicy() {
+    return contentSecurityPolicy;
+  }
+
+  public void addContentSecurityPolicy(String directive) {
+    contentSecurityPolicy.add(directive);
+  }
+
   public Map<String, String> getDefaultValidatorInfo() {
 
     // TODO: if the startup hasn't found a FacesContext and Application, this may depend on the order of the listeners.

Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParser.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParser.java?rev=1364930&r1=1364929&r2=1364930&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParser.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParser.java Tue Jul 24 08:08:50 2012
@@ -111,8 +111,13 @@ public class TobagoConfigParser {
     // session secret
     digester.addCallMethod("tobago-config/create-session-secret", "setCreateSessionSecret", 0);
     digester.addCallMethod("tobago-config/check-session-secret", "setCheckSessionSecret", 0);
+
+    // frame attacks
     digester.addBeanPropertySetter("tobago-config/prevent-frame-attacks", "preventFrameAttacks");
 
+    // content-security-policy
+    digester.addCallMethod("tobago-config/content-security-policy/directive", "addContentSecurityPolicy", 0);
+
     // renderer config
     digester.addObjectCreate("tobago-config/renderers", RenderersConfigImpl.class);
     digester.addSetNext("tobago-config/renderers", "setRenderersConfig");

Modified: myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseUtils.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseUtils.java?rev=1364930&r1=1364929&r2=1364930&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseUtils.java (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseUtils.java Tue Jul 24 08:08:50 2012
@@ -17,12 +17,15 @@ package org.apache.myfaces.tobago.intern
  * limitations under the License.
  */
 
+import org.apache.myfaces.tobago.context.ClientProperties;
+import org.apache.myfaces.tobago.context.UserAgent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 import javax.servlet.http.HttpServletResponse;
+import java.util.List;
 
 public class ResponseUtils {
 
@@ -74,4 +77,21 @@ public class ResponseUtils {
       }
     }
   }
+
+  public static void ensureContentSecurityPolicyHeader(FacesContext facesContext, List<String> contentSecurityPolicy) {
+    // TODO PortletRequest
+    if (facesContext.getExternalContext().getResponse() instanceof HttpServletResponse) {
+      final UserAgent userAgent = ClientProperties.getInstance(facesContext).getUserAgent();
+      final String cspHeader = userAgent.getCspHeader();
+      if (cspHeader != null) {
+        final StringBuilder value = new StringBuilder();
+        for (String directive : contentSecurityPolicy) {
+          value.append(directive);
+          value.append(";");
+        }
+        final HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
+        response.setHeader(cspHeader, value.toString());
+      }
+    }
+  }
 }

Modified: myfaces/tobago/trunk/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.6.xsd
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.6.xsd?rev=1364930&r1=1364929&r2=1364930&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.6.xsd (original)
+++ myfaces/tobago/trunk/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.6.xsd Tue Jul 24 08:08:50 2012
@@ -58,6 +58,7 @@
       <xs:element name="create-session-secret" type="xs:boolean" minOccurs="0"/>
       <xs:element name="check-session-secret" type="xs:boolean" minOccurs="0"/>
       <xs:element name="prevent-frame-attacks" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="content-security-policy" type="tobago:content-security-policy-type" minOccurs="0"/>
       <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
       <xs:element name="theme-definitions" type="tobago:theme-definitions-type" minOccurs="0"/>
     </xs:sequence>
@@ -92,6 +93,12 @@
     </xs:sequence>
   </xs:complexType>
 
+  <xs:complexType name="content-security-policy-type">
+    <xs:sequence>
+      <xs:element name="directive" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
   <xs:complexType name="renderers-type">
     <xs:sequence>
       <xs:element name="renderer" type="tobago:renderer-type" maxOccurs="unbounded"/>

Modified: myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/tobago-config.xml
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/tobago-config.xml?rev=1364930&r1=1364929&r2=1364930&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/tobago-config.xml (original)
+++ myfaces/tobago/trunk/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/tobago-config.xml Tue Jul 24 08:08:50 2012
@@ -20,8 +20,8 @@
 <tobago-config
     xmlns="http://myfaces.apache.org/tobago/tobago-config"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-1.5.xsd"
-    version="1.5">
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-1.6.xsd"
+    version="1.6">
 
   <name>demo</name>
 
@@ -44,6 +44,19 @@
 
   <resource-dir>tobago-resource</resource-dir>
 
+<!-- enable this to test CSP
+  <content-security-policy>
+    <directive>default-src 'self'</directive>
+  </content-security-policy>
+-->
+
+<!-- this may be an alternative way to define (not implemented)
+  <content-security-policy>
+    <default-src>'self'</default-src>
+    <image-src>images.irian.eu</image-src>
+  </content-security-policy>
+-->
+
   <renderers>
 
     <renderer>

Modified: myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/PageRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/PageRenderer.java?rev=1364930&r1=1364929&r2=1364930&view=diff
==============================================================================
--- myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/PageRenderer.java (original)
+++ myfaces/tobago/trunk/tobago-theme/tobago-theme-scarborough/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/PageRenderer.java Tue Jul 24 08:08:50 2012
@@ -125,7 +125,8 @@ public class PageRenderer extends PageRe
   @Override
   public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
 
-    UIPage page = (UIPage) component;
+    final UIPage page = (UIPage) component;
+    final TobagoConfig tobagoConfig = TobagoConfig.getInstance(facesContext);
 
     // invoke prepareRender
     RenderUtils.prepareRendererAll(facesContext, page);
@@ -142,6 +143,8 @@ public class PageRenderer extends PageRe
 
     ResponseUtils.ensureNoCacheHeader(facesContext);
 
+    ResponseUtils.ensureContentSecurityPolicyHeader(facesContext, tobagoConfig.getContentSecurityPolicy());
+
     if (LOG.isDebugEnabled()) {
       for (Object o : page.getAttributes().entrySet()) {
         Map.Entry entry = (Map.Entry) o;
@@ -158,7 +161,7 @@ public class PageRenderer extends PageRe
     ResponseUtils.ensureContentTypeHeader(facesContext, contentType);
     String clientId = page.getClientId(facesContext);
     final ClientProperties client = VariableResolverUtils.resolveClientProperties(facesContext);
-    final ProjectStage projectStage = TobagoConfig.getInstance(facesContext).getProjectStage();
+    final ProjectStage projectStage = tobagoConfig.getProjectStage();
     final boolean developmentMode =  projectStage == ProjectStage.Development;
     final boolean debugMode = client.isDebugMode() || developmentMode;
     final boolean productionMode = !debugMode && projectStage == ProjectStage.Production;
@@ -178,7 +181,7 @@ public class PageRenderer extends PageRe
         } catch (NumberFormatException e) {/* ignore; use default*/ }
       }
     }
-    boolean frameKiller = TobagoConfig.getInstance(facesContext).isPreventFrameAttacks();
+    boolean frameKiller = tobagoConfig.isPreventFrameAttacks();
 
     if (!FacesContextUtils.isAjax(facesContext)) {
       HtmlRendererUtils.renderDojoDndSource(facesContext, component);