Skip to content

Commit

Permalink
Allow secure variant if scheme-source only
Browse files Browse the repository at this point in the history
  • Loading branch information
shekyan committed Dec 13, 2016
1 parent 9475d9a commit 23862e1
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 47 deletions.
4 changes: 0 additions & 4 deletions src/main/java/com/shapesecurity/salvation/data/Policy.java
Expand Up @@ -364,10 +364,6 @@ private boolean defaultsAllowNonce(@Nonnull String nonce) {
return defaultSrcDirective.matchesNonce(nonce);
}

private boolean defaultsAllowNonce(@Nonnull Base64Value nonce) {
return this.defaultsAllowNonce(nonce.value);
}

private boolean defaultsAllowSource(@Nonnull URI source) {
DefaultSrcDirective defaultSrcDirective = this.getDirectiveByType(DefaultSrcDirective.class);
if (defaultSrcDirective == null) {
Expand Down
Expand Up @@ -78,4 +78,23 @@ public boolean isNetworkScheme() {
public boolean isSecureScheme() {
return isSchemeSecureScheme(this.scheme);
}

public static boolean matchesSecureScheme(@Nonnull String expressionScheme, @Nonnull String resourceScheme) {
expressionScheme = expressionScheme.toLowerCase();
resourceScheme = resourceScheme.toLowerCase();

if (expressionScheme.equals(resourceScheme))
return true;

if(expressionScheme.equals("http") && resourceScheme.equals("https"))
return true;

if(expressionScheme.equals("ws") && (resourceScheme.equals("wss") || resourceScheme.equals("http") || resourceScheme.equals("https")))
return true;

if(expressionScheme.equals("wss") && resourceScheme.equals("https"))
return true;

return false;
}
}
Expand Up @@ -72,18 +72,9 @@ public boolean isWildcard() {
}
boolean schemeMatches;
if (this.scheme == null) {
schemeMatches = resource.isNetworkScheme() ?
shpOrigin.isNetworkScheme() :
resource.scheme.equalsIgnoreCase(shpOrigin.scheme);
schemeMatches = SchemeHostPortTriple.matchesSecureScheme(shpOrigin.scheme, resource.scheme);
} else {
if (resource.isNetworkScheme() && !resource.scheme.equalsIgnoreCase("ftp") && !this.scheme.equalsIgnoreCase("ftp")) {
schemeMatches = resource.isSecureScheme() ?
SchemeHostPortTriple.isSchemeNetworkScheme(this.scheme) :
!SchemeHostPortTriple.isSchemeSecureScheme(this.scheme);

} else {
schemeMatches = this.scheme.equalsIgnoreCase(resource.scheme);
}
schemeMatches = SchemeHostPortTriple.matchesSecureScheme(this.scheme, resource.scheme);
}
boolean hostMatches = this.host.equals("*") || (this.host.startsWith("*.") ?
resource.host.toLowerCase().endsWith(this.host.substring(1).toLowerCase()) :
Expand Down
Expand Up @@ -18,8 +18,7 @@ public SchemeSource(@Nonnull String value) {
}

@Override public boolean matchesSource(@Nonnull Origin origin, @Nonnull URI resource) {
SchemeHostPortTriple shpOrigin = (SchemeHostPortTriple) origin;
return this.value.matches(resource.scheme);
return SchemeHostPortTriple.matchesSecureScheme(this.value, resource.scheme);
}

@Override public boolean matchesSource(@Nonnull Origin origin, @Nonnull GUID resource) {
Expand Down
115 changes: 85 additions & 30 deletions src/test/java/com/shapesecurity/salvation/PolicyQueryingTest.java
Expand Up @@ -104,23 +104,23 @@ public class PolicyQueryingTest extends CSPTest {
p = Parser.parse("default-src *:*", "http://abc.com");
assertTrue("resource is allowed", p.allowsImgFromSource(URI.parse("http://abc.am")));
assertTrue("resource is allowed", p.allowsScriptFromSource(URI.parse("https://www.def.am:555")));
assertTrue("resource is allowed", p.allowsStyleFromSource(URI.parse("ftp://www.abc.am:555")));
assertFalse("resource is not allowed", p.allowsStyleFromSource(URI.parse("ftp://www.abc.am:555")));

p = Parser.parse("default-src 'none'; frame-src http:;", URI.parse("https://abc.com"));
assertFalse("resource is not allowed", p.allowsFrameFromSource(URI.parse("https://www.def.am:555")));
assertTrue("resource is allowed", p.allowsFrameFromSource(URI.parse("https://www.def.am:555")));
assertTrue("resource is allowed", p.allowsFrameFromSource(URI.parse("http://www.def.am:555")));
assertFalse("resource is not allowed", p.allowsChildFromSource(URI.parse("http://www.def.am:555")));

p = Parser.parse("child-src http:;", URI.parse("https://abc.com"));
assertFalse("resource is not allowed", p.allowsFrameFromSource(URI.parse("https://www.def.am:555")));
assertTrue("resource is allowed", p.allowsFrameFromSource(URI.parse("https://www.def.am:555")));
assertTrue("resource is allowed", p.allowsFrameFromSource(URI.parse("http://www.def.am:555")));
assertFalse("resource is not allowed", p.allowsChildFromSource(URI.parse("https://www.def.am:555")));
assertTrue("resource is not allowed", p.allowsChildFromSource(URI.parse("https://www.def.am:555")));
assertTrue("resource is allowed", p.allowsChildFromSource(URI.parse("http://www.def.am:555")));

p = Parser.parse("frame-src https:; child-src http:;", URI.parse("https://abc.com"));
assertTrue("resource is allowed", p.allowsFrameFromSource(URI.parse("https://www.def.am:555")));
assertFalse("resource is not allowed", p.allowsFrameFromSource(URI.parse("http://www.def.am:555")));
assertFalse("resource is not allowed", p.allowsChildFromSource(URI.parse("https://www.def.am:555")));
assertTrue("resource is allowed", p.allowsChildFromSource(URI.parse("https://www.def.am:555")));
assertTrue("resource is allowed", p.allowsChildFromSource(URI.parse("http://www.def.am:555")));

p = Parser.parse("font-src https://font.com http://font.org", URI.parse("https://abc.com"));
Expand Down Expand Up @@ -151,6 +151,61 @@ public class PolicyQueryingTest extends CSPTest {

@Test public void testSecureSchemes() {
Policy p;

p = Parser.parse("script-src http:;", "http://example.com");
assertTrue(p.allowsScriptFromSource(URI.parse("http://a")));

p = Parser.parse("script-src http:;", "http://example.com");
assertFalse(p.allowsScriptFromSource(URI.parse("ws://a")));

p = Parser.parse("script-src http:;", "http://example.com");
assertFalse(p.allowsScriptFromSource(URI.parse("wss://a")));

p = Parser.parse("script-src http:;", "http://example.com");
assertTrue(p.allowsScriptFromSource(URI.parse("https://a")));

p = Parser.parse("script-src http:;", "http://example.com");
assertFalse(p.allowsScriptFromSource(URI.parse("ftp://a")));

p = Parser.parse("script-src http:;", "http://example.com");
assertFalse(p.allowsScriptFromSource(URI.parse("sftp://a")));

p = Parser.parse("script-src ws:;", "http://example.com");
assertTrue(p.allowsScriptFromSource(URI.parse("http://a")));

p = Parser.parse("script-src ws:;", "http://example.com");
assertTrue(p.allowsScriptFromSource(URI.parse("ws://a")));

p = Parser.parse("script-src ws:;", "http://example.com");
assertTrue(p.allowsScriptFromSource(URI.parse("wss://a")));

p = Parser.parse("script-src ws:;", "http://example.com");
assertTrue(p.allowsScriptFromSource(URI.parse("https://a")));

p = Parser.parse("script-src ws:;", "http://example.com");
assertFalse(p.allowsScriptFromSource(URI.parse("ftp://a")));

p = Parser.parse("script-src ws:;", "http://example.com");
assertFalse(p.allowsScriptFromSource(URI.parse("sftp://a")));

p = Parser.parse("script-src wss:;", "http://example.com");
assertFalse(p.allowsScriptFromSource(URI.parse("http://a")));

p = Parser.parse("script-src wss:;", "http://example.com");
assertFalse(p.allowsScriptFromSource(URI.parse("ws://a")));

p = Parser.parse("script-src wss:;", "http://example.com");
assertTrue(p.allowsScriptFromSource(URI.parse("wss://a")));

p = Parser.parse("script-src wss:;", "http://example.com");
assertTrue(p.allowsScriptFromSource(URI.parse("https://a")));

p = Parser.parse("script-src wss:;", "http://example.com");
assertFalse(p.allowsScriptFromSource(URI.parse("ftp://a")));

p = Parser.parse("script-src wss:;", "http://example.com");
assertFalse(p.allowsScriptFromSource(URI.parse("sftp://a")));

p = Parser.parse("script-src a;", "http://example.com");
assertTrue(p.allowsScriptFromSource(URI.parse("https://a")));

Expand Down Expand Up @@ -555,8 +610,8 @@ public class PolicyQueryingTest extends CSPTest {
assertFalse(p.allowsScriptFromSource(URI.parse("ftp://example.com:80")));
assertTrue(p.allowsScriptFromSource(URI.parse("http://example.com/path")));
assertTrue(p.allowsScriptFromSource(URI.parse("http://example.com/PATH")));
assertTrue(p.allowsScriptFromSource(URI.parse("ws://example.com/PATH")));
assertTrue(p.allowsScriptFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsScriptFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsScriptFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsScriptFromSource(new GUID("data:")));
assertFalse(p.allowsScriptFromSource(new GUID("custom.scheme:")));

Expand All @@ -565,34 +620,34 @@ public class PolicyQueryingTest extends CSPTest {
assertFalse(p.allowsStyleFromSource(URI.parse("https://example.com")));
assertFalse(p.allowsStyleFromSource(URI.parse("http://example.com:81")));
assertFalse(p.allowsStyleFromSource(URI.parse("ftp://example.com")));
assertTrue(p.allowsStyleFromSource(URI.parse("ftp://example.com:80")));
assertFalse(p.allowsStyleFromSource(URI.parse("ftp://example.com:80")));
assertTrue(p.allowsStyleFromSource(URI.parse("http://example.com/path")));
assertTrue(p.allowsStyleFromSource(URI.parse("http://example.com/PATH")));
assertTrue(p.allowsStyleFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(new GUID("data:")));
assertFalse(p.allowsStyleFromSource(new GUID("custom.scheme:")));

p = Parser.parse("style-src *:80", "https://example.com");
assertTrue(p.allowsStyleFromSource(URI.parse("http://example.com")));
assertFalse(p.allowsStyleFromSource(URI.parse("http://example.com")));
assertFalse(p.allowsStyleFromSource(URI.parse("https://example.com")));
assertFalse(p.allowsStyleFromSource(URI.parse("http://example.com:81")));
assertFalse(p.allowsStyleFromSource(URI.parse("ftp://example.com")));
assertTrue(p.allowsStyleFromSource(URI.parse("ftp://example.com:80")));
assertTrue(p.allowsStyleFromSource(URI.parse("http://example.com/path")));
assertTrue(p.allowsStyleFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(URI.parse("ftp://example.com:80")));
assertFalse(p.allowsStyleFromSource(URI.parse("http://example.com/path")));
assertFalse(p.allowsStyleFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(new GUID("data:")));
assertFalse(p.allowsStyleFromSource(new GUID("custom.scheme:")));

p = Parser.parse("style-src *:80", "ftp://example.com");
assertTrue(p.allowsStyleFromSource(URI.parse("http://example.com")));
assertFalse(p.allowsStyleFromSource(URI.parse("http://example.com")));
assertFalse(p.allowsStyleFromSource(URI.parse("https://example.com")));
assertFalse(p.allowsStyleFromSource(URI.parse("http://example.com:81")));
assertFalse(p.allowsStyleFromSource(URI.parse("ftp://example.com")));
assertTrue(p.allowsStyleFromSource(URI.parse("ftp://example.com:80")));
assertTrue(p.allowsStyleFromSource(URI.parse("http://example.com/path")));
assertTrue(p.allowsStyleFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(URI.parse("http://example.com/path")));
assertFalse(p.allowsStyleFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(new GUID("data:")));
assertFalse(p.allowsStyleFromSource(new GUID("custom.scheme:")));
Expand All @@ -613,11 +668,11 @@ public class PolicyQueryingTest extends CSPTest {
assertTrue(p.allowsStyleFromSource(URI.parse("http://example.com")));
assertTrue(p.allowsStyleFromSource(URI.parse("https://example.com")));
assertTrue(p.allowsStyleFromSource(URI.parse("http://example.com:81")));
assertTrue(p.allowsStyleFromSource(URI.parse("ftp://example.com")));
assertTrue(p.allowsStyleFromSource(URI.parse("ftp://example.com:80")));
assertFalse(p.allowsStyleFromSource(URI.parse("ftp://example.com")));
assertFalse(p.allowsStyleFromSource(URI.parse("ftp://example.com:80")));
assertTrue(p.allowsStyleFromSource(URI.parse("http://example.com/path")));
assertTrue(p.allowsStyleFromSource(URI.parse("ws://example.com/PATH")));
assertTrue(p.allowsStyleFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(new GUID("data:")));
assertFalse(p.allowsStyleFromSource(new GUID("custom.scheme:")));

Expand All @@ -628,8 +683,8 @@ public class PolicyQueryingTest extends CSPTest {
assertFalse(p.allowsStyleFromSource(URI.parse("ftp://example.com")));
assertFalse(p.allowsStyleFromSource(URI.parse("ftp://example.com:80")));
assertTrue(p.allowsStyleFromSource(URI.parse("http://example.com/path")));
assertTrue(p.allowsStyleFromSource(URI.parse("ws://example.com/PATH")));
assertTrue(p.allowsStyleFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsStyleFromSource(new GUID("data:")));
assertFalse(p.allowsStyleFromSource(new GUID("custom.scheme:")));

Expand Down Expand Up @@ -689,8 +744,8 @@ public class PolicyQueryingTest extends CSPTest {
assertFalse(p.allowsFontFromSource(URI.parse("ftp://example.com:80")));
assertTrue(p.allowsFontFromSource(URI.parse("http://example.com/path")));
assertTrue(p.allowsFontFromSource(URI.parse("http://example.com/PATH")));
assertTrue(p.allowsFontFromSource(URI.parse("ws://example.com/PATH")));
assertTrue(p.allowsFontFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsFontFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsFontFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsFontFromSource(new GUID("data:")));
assertFalse(p.allowsFontFromSource(new GUID("custom.scheme:")));

Expand Down Expand Up @@ -726,8 +781,8 @@ public class PolicyQueryingTest extends CSPTest {
assertFalse(p.allowsObjectFromSource(URI.parse("ftp://example.com:80")));
assertTrue(p.allowsObjectFromSource(URI.parse("http://example.com/path")));
assertTrue(p.allowsObjectFromSource(URI.parse("http://example.com/PATH")));
assertTrue(p.allowsObjectFromSource(URI.parse("ws://example.com/PATH")));
assertTrue(p.allowsObjectFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsObjectFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsObjectFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsObjectFromSource(new GUID("data:")));
assertFalse(p.allowsObjectFromSource(new GUID("custom.scheme:")));

Expand Down Expand Up @@ -763,8 +818,8 @@ public class PolicyQueryingTest extends CSPTest {
assertFalse(p.allowsMediaFromSource(URI.parse("ftp://example.com:80")));
assertTrue(p.allowsMediaFromSource(URI.parse("http://example.com/path")));
assertTrue(p.allowsMediaFromSource(URI.parse("http://example.com/PATH")));
assertTrue(p.allowsMediaFromSource(URI.parse("ws://example.com/PATH")));
assertTrue(p.allowsMediaFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsMediaFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsMediaFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsMediaFromSource(new GUID("data:")));
assertFalse(p.allowsMediaFromSource(new GUID("custom.scheme:")));

Expand Down Expand Up @@ -800,8 +855,8 @@ public class PolicyQueryingTest extends CSPTest {
assertFalse(p.allowsManifestFromSource(URI.parse("ftp://example.com:80")));
assertTrue(p.allowsManifestFromSource(URI.parse("http://example.com/path")));
assertTrue(p.allowsManifestFromSource(URI.parse("http://example.com/PATH")));
assertTrue(p.allowsManifestFromSource(URI.parse("ws://example.com/PATH")));
assertTrue(p.allowsManifestFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsManifestFromSource(URI.parse("ws://example.com/PATH")));
assertFalse(p.allowsManifestFromSource(URI.parse("wss://example.com/PATH")));
assertFalse(p.allowsManifestFromSource(new GUID("data:")));
assertFalse(p.allowsManifestFromSource(new GUID("custom.scheme:")));

Expand Down

0 comments on commit 23862e1

Please sign in to comment.