Permalink
Browse files

Updates in preparation for 1.0

  • Loading branch information...
1 parent e05277a commit 921a7c2826188081a80b0b9fbc608dd7762e24d1 @eoftedal committed Aug 28, 2012
@@ -8,6 +8,7 @@ namespace ContentSecurityPolicy.Net.Config
{
public class ContentSecurityPolicySection : ConfigurationSection
{
+
[ConfigurationProperty("reportOnly")]
public bool ReportOnly
{
@@ -19,11 +20,6 @@ public Uri ReportUri
get { return (Uri)this["reportUri"]; }
}
- [ConfigurationProperty("options", IsRequired = false)]
- public OptionsElement Options
- {
- get { return (OptionsElement)this["options"]; }
- }
[ConfigurationProperty("allowedSources", IsRequired = false)]
public PolicyDirectiveElement AllowedSources
@@ -60,10 +56,10 @@ public PolicyDirectiveElement AllowedFontSources
{
get { return (PolicyDirectiveElement)this["allowedFontSources"]; }
}
- [ConfigurationProperty("allowedXhrSources", IsRequired = false)]
- public PolicyDirectiveElement AllowedXhrSources
+ [ConfigurationProperty("allowedConnectSources", IsRequired = false)]
+ public PolicyDirectiveElement AllowedConnectSources
{
- get { return (PolicyDirectiveElement)this["allowedXhrSources"]; }
+ get { return (PolicyDirectiveElement)this["allowedConnectSources"]; }
}
[ConfigurationProperty("allowedFrameAncestors", IsRequired = false)]
public PolicyDirectiveElement AllowedFrameAncestors
@@ -76,8 +72,15 @@ public UnsafeInlineDirectiveElement AllowedStyleSources
get { return (UnsafeInlineDirectiveElement)this["allowedStyleSources"]; }
}
+
+
+
+
public Policy ToPolicy()
{
+
+
+
var policy = new Policy {ReportOnlyMode = ReportOnly, ReportUri = ReportUri};
policy.AddDirective(AllowedSources.AsDirective("default-src"));
policy.AddDirective(AllowedFontSources.AsDirective("font-src"));
@@ -87,12 +90,8 @@ public Policy ToPolicy()
policy.AddDirective(AllowedMediaSources.AsDirective("media-src"));
policy.AddDirective(AllowedObjectSources.AsDirective("object-src"));
policy.AddDirective(AllowedStyleSources.AsDirective("style-src"));
- policy.AddDirective(AllowedXhrSources.AsDirective("xhr-src"));
- var scriptDirective = (UriPolicyDirective)AllowedScriptSources.AsDirective("script-src");
- if (Options != null)
- {
- }
- policy.AddDirective(scriptDirective);
+ policy.AddDirective(AllowedConnectSources.AsAliasedDirective("connect-src", "xhr-src"));
+ policy.AddDirective(AllowedScriptSources.AsDirective("script-src"));
return policy;
}
}
@@ -1,23 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Configuration;
-
-namespace ContentSecurityPolicy.Net.Config
-{
- public class OptionsElement : ConfigurationElement
- {
- [ConfigurationProperty("allowInlineScript")]
- public bool AllowInlineScripts
- {
- get { return (bool)this["allowInlineScript"]; }
- }
- [ConfigurationProperty("allowScriptEval")]
- public bool AllowScriptEval
- {
- get { return (bool)this["allowScriptEval"]; }
- }
-
- }
-}
@@ -27,7 +27,12 @@ public virtual PolicyDirective ToDirective(String name)
var directive = new UriPolicyDirective(name);
AddSourcesAndSelf(directive);
return directive;
-
+ }
+ public virtual PolicyDirective ToAliasedDirective(String name, String oldName)
+ {
+ var directive = new UriPolicyDirective(name, oldName);
+ AddSourcesAndSelf(directive);
+ return directive;
}
protected void AddSourcesAndSelf(UriPolicyDirective directive)
@@ -45,6 +50,11 @@ public static PolicyDirective AsDirective(this PolicyDirectiveElement element, s
if (element == null) return null;
return element.ToDirective(name);
}
+ public static PolicyDirective AsAliasedDirective(this PolicyDirectiveElement element, string name, string oldName)
+ {
+ if (element == null) return null;
+ return element.ToAliasedDirective(name, oldName);
+ }
}
@@ -13,6 +13,12 @@ public bool UnsafeAllowEval
{
get { return (bool)this["unsafeAllowEval"]; }
}
+ public bool HasUnsafeAllowEval
+ {
+ get { return this["unsafeAllowEval"] != null; }
+ }
+
+
public override PolicyDirective ToDirective(string name)
{
var directive = new ScriptPolicyDirective
@@ -9,6 +9,12 @@ public bool UnsafeAllowInline
{
get { return (bool)this["unsafeAllowInline"]; }
}
+ public bool HasUnsafeAllowInline
+ {
+ get { return this["unsafeAllowInline"] != null; }
+ }
+
+
public override PolicyDirective ToDirective(string name)
{
var directive = new UnsafeInlinePolicyDirective(name) {UnsafeAllowInline = UnsafeAllowInline};
@@ -45,7 +45,6 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Config\UnsafeInlineDirectiveElement.cs" />
- <Compile Include="Config\OptionsElement.cs" />
<Compile Include="Config\PolicyDirectiveElement.cs" />
<Compile Include="Config\ContentSecurityPolicySection.cs" />
<Compile Include="Config\ScriptDirectiveElement.cs" />
@@ -51,18 +51,15 @@ private string GetReportingPart()
public string GetHeaderValue(string useragent)
{
var agent = new Useragent(useragent);
+ CspVersion version = agent.IsFirefox() ? CspVersion.Ff4To7 : CspVersion.Latest;
return _policyDirectives
- .OrderBy(p => p.DirectiveName == "options" ? "1" : ("2" + p.DirectiveName))
- .Select(p => AsString(p, agent))
+ .OrderBy(p => p.GetDirectiveName(version) == "options" ? "1" : ("2" + p.GetDirectiveName(version)))
+ .Select(p => p.ToHeaderString(version))
.Where(s => !string.IsNullOrEmpty(s))
.Aggregate((s1, s2) => s1 + "; " + s2)
+ ReportUriPart;
}
- private static string AsString(PolicyDirective directive, Useragent useragent)
- {
- return directive.ToHeaderString(useragent.IsFirefox() ? CspVersion.Ff4To7 : CspVersion.Latest);
- }
@@ -13,23 +13,36 @@ public enum CspVersion
public abstract class PolicyDirective
{
- public string DirectiveName { get; protected set; }
+ private String _directiveName;
+ private String _oldName;
+ public virtual string GetDirectiveName(CspVersion version)
+ {
+ return _directiveName;
+ }
public abstract string ToHeaderString(CspVersion version);
+ public PolicyDirective(string directiveName)
+ {
+ _directiveName = directiveName;
+ }
+ public PolicyDirective(string directiveName, string oldName)
+ {
+ _directiveName = directiveName;
+ _oldName = oldName;
+ }
}
public class UriPolicyDirective : PolicyDirective
{
private readonly List<Source> _allowedSourceList = new List<Source>();
public bool IncludeSelf { get; set; }
- public UriPolicyDirective(string directiveName)
- {
- DirectiveName = directiveName;
- }
+ public UriPolicyDirective(string directiveName) : base(directiveName) { }
+ public UriPolicyDirective(string directiveName, string oldName) : base(directiveName, oldName) { }
+
public override string ToHeaderString(CspVersion version)
{
if (HasNoSources()) return "";
- return DirectiveName
+ return GetDirectiveName(version)
+ (IncludeSelf ? " 'self' " : " ")
+ ImplodeSources();
}
@@ -52,6 +65,8 @@ public void AddSource(Source source)
_allowedSourceList.Add(source);
}
}
+
+
public class UnsafeInlinePolicyDirective : UriPolicyDirective
{
public bool UnsafeAllowInline { get; set; }
@@ -61,10 +76,10 @@ public UnsafeInlinePolicyDirective(String name)
{
}
- public string ToHeaderString()
+ public override string ToHeaderString(CspVersion version)
{
if (UnsafeAllowInline == false && HasNoSources()) return "";
- return DirectiveName + " " +
+ return GetDirectiveName(version) + " " +
(UnsafeAllowInline ? "'unsafe-inline' " : "")
+ ImplodeSources();
}
@@ -90,10 +105,10 @@ public override string ToHeaderString(CspVersion version)
(UnsafeAllowInline ? "inline-script" : "") + ";";
}
if (HasNoSources()) return header;
- return header + DirectiveName + " " + ImplodeSources();
+ return header + GetDirectiveName(version) + " " + ImplodeSources();
}
if (!UnsafeAllowInline && !UnsafeAllowEval && HasNoSources()) return "";
- return DirectiveName + " "
+ return GetDirectiveName(version) + " "
+ (UnsafeAllowInline ? "'unsafe-inline' " : "")
+ (UnsafeAllowEval ? "'unsafe-eval' " : "")
+ ImplodeSources();
@@ -20,24 +20,9 @@ public bool IsReusable
public void ProcessRequest(HttpContext context)
{
- if (new Useragent(context.Request.UserAgent).IsFirefox())
- {
- var des = new DataContractJsonSerializer(typeof (CspReport));
- var wrappedReport = des.ReadObject(context.Request.InputStream) as CspReport;
- HandleReport(wrappedReport.Report);
- } else
- {
- var report = new Report();
- using(var reader = new StreamReader(context.Request.InputStream))
- {
- var urlencodedReport = reader.ReadToEnd();
- var parts = urlencodedReport.Split('&').Select(s => s.Split(new[] {'='}, 2)).ToDictionary(
- s => s[0], s => HttpUtility.UrlDecode(s[1]));
- report.ViolatedDirective = parts["violated-directive"];
- report.Request = parts["document-url"];
- HandleReport(report);
- }
- }
+ var des = new DataContractJsonSerializer(typeof (CspReport));
+ var wrappedReport = des.ReadObject(context.Request.InputStream) as CspReport;
+ HandleReport(wrappedReport.Report);
}
protected abstract void HandleReport(Report report);
}
@@ -9,12 +9,12 @@ namespace ContentSecurityPolicy.Net.Reports
[DataContract]
public class Report
{
- [DataMember(Name="request")]
- public string Request;
- [DataMember(Name = "request-headers")]
- public string RequestHeaders;
+ [DataMember(Name="document-uri")]
+ public String DocumentUri;
+ [DataMember(Name = "referrer")]
+ public string Referrer;
[DataMember(Name = "blocked-uri")]
- public string BlockedUri;
+ public String BlockedUri;
[DataMember(Name = "violated-directive")]
public string ViolatedDirective;
[DataMember(Name = "original-policy")]
@@ -10,18 +10,17 @@
<section name="contentSecurityPolicy" type="ContentSecurityPolicy.Net.Config.ContentSecurityPolicySection"/>
</configSections>
<contentSecurityPolicy reportUri="csp-reporting/">
- <options allowInlineScript="true" />
<allowedSources allowSelf="true" />
<allowedImageSources>
<add source="https://*.cloudfront.net:443" />
</allowedImageSources>
<allowedObjectSources>
<add source="http://*.google.com" />
</allowedObjectSources>
- <allowedScriptSources>
+ <allowedScriptSources unsafeAllowEval="true">
<add source="http://erlend.oftedal.no" />
</allowedScriptSources>
- <allowedStyleSources>
+ <allowedStyleSources unsafeAllowInline="true">
<add source="http://erlend.oftedal.no" />
</allowedStyleSources>
<allowedFrameSources>
View
@@ -0,0 +1,51 @@
+## Goal:
+- 2012-08-28: Support the 1.0 version (but stay compatible with firefox) - This version *will break old configs* replacing options with allowedScriptSources unsafeAllowEval and unsafeAllowInline. allowedXhrSources is now allowedConnectSources
+- 2011-09-29: Support the latest version from W3C, but stay compatible with firefox - adding 'unsafe-inline' and 'unsafe-eval'
+- 2011-06-21: Support the latest version from W3C, but stay compatible with earlier versions in firefox and chrome
+- 2011-06-15: Support the Chrome version as well, allthough this support is a bit experimental from Chrome's side
+- Allow the specification of the content security policy as a part of web.config
+- Allow the policy to be used as an HttpModule so there is no need to add to pages etc. to enable it
+
+## Testing
+Verified via webtest project so far:
+ img-src, object-src, script-src, style-src, frame-src
+
+## Web.config policy:
+ <contentSecurityPolicy reportOnly="true" reportUri="csp-reporting/">
+ <allowedSources allowSelf="true" unsafeAllowInline="true" />
+ <allowedImageSources>
+ <add source="*" />
+ </allowedImageSources>
+ <allowedScriptSources allowSelf="true" unsafeAllowEval="true">
+ <add source="*.google.com" />
+ </allowedScriptSources>
+ </contentSecurityPolicy>
+
+## Web.config for HttpModule:
+ <httpModules>
+ <add name="ContentSecurityPolicyHttpModule" type="ContentSecurityPolicy.Net.PolicyHttpModule, ContentSecurityPolicy.Net"/>
+ </httpModules>
+
+
+## Abstract HTTP handler for receiving CSP failure reports
+Code for handler:
+
+ public class ReportHandler : AbstractReportHandler
+ {
+ protected override void HandleReport(Report report)
+ {
+ //Store data here
+ }
+ }
+
+
+Web.config policy definition for reportUri:
+
+ <contentSecurityPolicy reportUri="csp-reporting/">
+
+
+Web.config httphandler config:
+
+ <httpHandlers>
+ <add path="csp-reporting/" verb="POST" type="ContentSecurityPolicy.Net.WebTest.ReportHandler, ContentSecurityPolicy.Net.WebTest"/>
+ </httpHandlers>
Oops, something went wrong.

0 comments on commit 921a7c2

Please sign in to comment.