Skip to content
This repository has been archived by the owner on Apr 3, 2020. It is now read-only.

Commit

Permalink
Add SuboriginPolicy header and unsafe-postmessage-send directive
Browse files Browse the repository at this point in the history
This adds a SuboriginPolicy header that takes policies to bypass certain
Suborigin restrictions. It also adds a specific unsafe-postmessage-send
directive that specifies that the receiving end of a postMessage message
event should seed the origin as the physical origin, rather than the
serialized suborigin.

BUG=336894

Review URL: https://codereview.chromium.org/1772873003

Cr-Commit-Position: refs/heads/master@{#381905}
  • Loading branch information
joelweinberger authored and Commit bot committed Mar 18, 2016
1 parent 92a2678 commit 0233ac7
Show file tree
Hide file tree
Showing 31 changed files with 486 additions and 230 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<?php
$suborigin = $_GET["suborigin"];
$suboriginPolicy = $_GET["suboriginpolicy"];

if ($_GET["suborigin"]) {
header("Suborigin: ". $_GET["suborigin"]);
header("Suborigin: " . $suborigin . " " . $suboriginPolicy);
}
?>
<!DOCTYPE html>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ CONSOLE ERROR: Error with Suborigin header: Invalid character ''' in suborigin.
ALERT: I am a secret
CONSOLE ERROR: Error with Suborigin header: Invalid character '@' in suborigin.
ALERT: I am a secret
CONSOLE ERROR: Error with Suborigin header: Whitespace is not allowed in suborigin names.
CONSOLE ERROR: Error with Suborigin header: Invalid character 'b' in suborigin policy. Suborigin policy options must start and end with a single quote.
ALERT: I am a secret
CONSOLE ERROR: Error with Suborigin header: Invalid character 'F' in suborigin.
ALERT: I am a secret
CONSOLE ERROR: Error with Suborigin header: Invalid character 'F' in suborigin.
ALERT: I am a secret

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"foo'bar",
"foob@r",
"foo bar",
"Foobar",
"FOOBAR",
];

var iframe;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<title>Validate that unsafe-postmessage-send allows Suborigin to send messages as physical origin via postMessage.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<script>
var iframe_test = async_test("Validate serialization of event.origin and event.suborigin in postMessage from an iframe");
var window_test = async_test("Validate serialization of event.origin and event.suborigin in postMessage from a window");

window.onmessage = function(event) {
if (event.data.type === 'iframe') {
iframe_test.step(function() {
assert_equals(event.origin, "http://127.0.0.1:8000");
assert_equals(event.suborigin, "foobar1");
assert_equals(event.data.suborigin, "foobar1");
iframe_test.done();
});
} else if (event.data.type === 'window') {
window_test.step(function() {
assert_equals(event.origin, "http://127.0.0.1:8000");
assert_equals(event.suborigin, "foobar2");
assert_equals(event.data.suborigin, "foobar2");;
window_test.done();
});
} else {
assert_unreached();
}

}

window.open("resources/post-document-to-parent.php?suborigin=foobar2&type=window&suboriginpolicy='unsafe-postmessage-send';");
</script>
<iframe src="resources/post-document-to-parent.php?suborigin=foobar1&type=iframe&suboriginpolicy='unsafe-postmessage-send';"></iframe>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@ ALERT: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from a
ALERT: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.
ALERT: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.
ALERT: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.
ALERT: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.
ALERT: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.

Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
var test_suborigin_names = [
"foobar",
"foob4r",
"Foobar",
"FOOBAR",
"42",
"foo-bar",
"-foobar",
Expand Down
4 changes: 0 additions & 4 deletions third_party/WebKit/Source/core/core.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -2563,8 +2563,6 @@
'dom/StyleSheetCandidate.h',
'dom/StyleSheetCollection.cpp',
'dom/StyleSheetCollection.h',
'dom/Suborigin.cpp',
'dom/Suborigin.h',
'dom/TagCollection.cpp',
'dom/TagCollection.h',
'dom/Text.cpp',
Expand Down Expand Up @@ -3928,7 +3926,6 @@
'dom/SelectorQueryTest.cpp',
'dom/StyleElementTest.cpp',
'dom/StyleEngineTest.cpp',
'dom/SuboriginTest.cpp',
'dom/TextTest.cpp',
'dom/TreeScopeStyleSheetCollectionTest.cpp',
'dom/TreeScopeTest.cpp',
Expand Down Expand Up @@ -4037,7 +4034,6 @@
'loader/LinkHeaderTest.cpp',
'loader/LinkLoaderTest.cpp',
'loader/MixedContentCheckerTest.cpp',
'origin_trials/DocumentOriginTrialContextTest.cpp',
'origin_trials/OriginTrialContextTest.cpp',
'page/ChromeClientTest.cpp',
'page/ContextMenuControllerTest.cpp',
Expand Down
5 changes: 4 additions & 1 deletion third_party/WebKit/Source/core/dom/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5005,7 +5005,7 @@ void Document::initSecurityContext(const DocumentInit& initializer)
}

if (getSecurityOrigin()->hasSuborigin())
enforceSuborigin(getSecurityOrigin()->suboriginName());
enforceSuborigin(*getSecurityOrigin()->suborigin());

if (Settings* settings = initializer.settings()) {
if (!settings->webSecurityEnabled()) {
Expand All @@ -5030,6 +5030,9 @@ void Document::initSecurityContext(const DocumentInit& initializer)

if (getSecurityOrigin()->isUnique() && SecurityOrigin::create(m_url)->isPotentiallyTrustworthy())
getSecurityOrigin()->setUniqueOriginIsPotentiallyTrustworthy(true);

if (getSecurityOrigin()->hasSuborigin())
enforceSuborigin(*getSecurityOrigin()->suborigin());
}

void Document::initContentSecurityPolicy(PassRefPtrWillBeRawPtr<ContentSecurityPolicy> csp)
Expand Down
2 changes: 1 addition & 1 deletion third_party/WebKit/Source/core/dom/Document.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ class CORE_EXPORT Document : public ContainerNode, public TreeScope, public Secu
void setHasXMLDeclaration(bool hasXMLDeclaration) { m_hasXMLDeclaration = hasXMLDeclaration ? 1 : 0; }

String origin() const { return getSecurityOrigin()->toString(); }
String suborigin() const { return getSecurityOrigin()->suboriginName(); }
String suborigin() const { return getSecurityOrigin()->hasSuborigin() ? getSecurityOrigin()->suborigin()->name() : String(); }

String visibilityState() const;
PageVisibilityState pageVisibilityState() const;
Expand Down
22 changes: 4 additions & 18 deletions third_party/WebKit/Source/core/dom/SecurityContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,34 +90,20 @@ String SecurityContext::addressSpaceForBindings() const
return "public";
}

bool SecurityContext::hasSuborigin()
{
ASSERT(m_securityOrigin.get());
return m_securityOrigin->hasSuborigin();
}

String SecurityContext::suboriginName()
{
ASSERT(m_securityOrigin.get());
return m_securityOrigin->suboriginName();
}

// Enforces the given suborigin as part of the security origin for this
// security context. |name| must not be empty, although it may be null. A null
// name represents a lack of a suborigin.
// See: https://w3c.github.io/webappsec-suborigins/index.html
void SecurityContext::enforceSuborigin(const String& name)
void SecurityContext::enforceSuborigin(const Suborigin& suborigin)
{
if (!RuntimeEnabledFeatures::suboriginsEnabled())
return;

if (name.isNull())
return;
ASSERT(!name.isEmpty());
ASSERT(!suborigin.name().isEmpty());
ASSERT(RuntimeEnabledFeatures::suboriginsEnabled());
ASSERT(m_securityOrigin.get());
ASSERT(!m_securityOrigin->hasSuborigin() || m_securityOrigin->suboriginName() == name);
m_securityOrigin->addSuborigin(name);
ASSERT(!m_securityOrigin->hasSuborigin() || m_securityOrigin->suborigin()->name() == suborigin.name());
m_securityOrigin->addSuborigin(suborigin);
didUpdateSecurityOrigin();
}

Expand Down
6 changes: 3 additions & 3 deletions third_party/WebKit/Source/core/dom/SecurityContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
#include "core/CoreExport.h"
#include "core/dom/SandboxFlags.h"
#include "platform/heap/Handle.h"
#include "platform/weborigin/Suborigin.h"
#include "public/platform/WebAddressSpace.h"
#include "public/platform/WebURLRequest.h"
#include "wtf/HashSet.h"
#include "wtf/Noncopyable.h"
#include "wtf/PassRefPtr.h"
Expand Down Expand Up @@ -83,9 +85,7 @@ class CORE_EXPORT SecurityContext : public WillBeGarbageCollectedMixin {
void setShouldEnforceStrictMixedContentChecking(bool shouldEnforce) { m_enforceStrictMixedContentChecking = shouldEnforce; }
bool shouldEnforceStrictMixedContentChecking() { return m_enforceStrictMixedContentChecking; }

void enforceSuborigin(const String& name);
bool hasSuborigin();
String suboriginName();
void enforceSuborigin(const Suborigin&);

protected:
SecurityContext();
Expand Down
62 changes: 0 additions & 62 deletions third_party/WebKit/Source/core/dom/Suborigin.cpp

This file was deleted.

23 changes: 0 additions & 23 deletions third_party/WebKit/Source/core/dom/Suborigin.h

This file was deleted.

63 changes: 0 additions & 63 deletions third_party/WebKit/Source/core/dom/SuboriginTest.cpp

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential
// which implies that all Suborigins are okay as well.
if (securityOrigin->hasSuborigin() && allowOriginHeaderValue != starAtom) {
const AtomicString& allowSuboriginHeaderValue = response.httpHeaderField(allowSuboriginHeaderName);
AtomicString atomicSuboriginName(securityOrigin->suboriginName());
AtomicString atomicSuboriginName(securityOrigin->suborigin()->name());
if (allowSuboriginHeaderValue != starAtom && allowSuboriginHeaderValue != atomicSuboriginName) {
errorDescription = buildAccessControlFailureMessage("The 'Access-Control-Allow-Suborigin' header has a value '" + allowSuboriginHeaderValue + "' that is not equal to the supplied suborigin.", securityOrigin);
return false;
Expand Down
10 changes: 8 additions & 2 deletions third_party/WebKit/Source/core/frame/DOMWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "core/page/Page.h"
#include "platform/weborigin/KURL.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/weborigin/Suborigin.h"

namespace blink {

Expand Down Expand Up @@ -199,8 +200,13 @@ void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const Mes
// in order to capture the source of the message correctly.
if (!sourceDocument)
return;
String sourceOrigin = sourceDocument->getSecurityOrigin()->toString();
String sourceSuborigin = sourceDocument->getSecurityOrigin()->suboriginName();

const SecurityOrigin* securityOrigin = sourceDocument->getSecurityOrigin();
bool hasSuborigin = sourceDocument->getSecurityOrigin()->hasSuborigin();
Suborigin::SuboriginPolicyOptions unsafeSendOpt = Suborigin::SuboriginPolicyOptions::UnsafePostMessageSend;

String sourceOrigin = (hasSuborigin && securityOrigin->suborigin()->policyContains(unsafeSendOpt)) ? securityOrigin->toPhysicalOriginString() : securityOrigin->toString();
String sourceSuborigin = hasSuborigin ? securityOrigin->suborigin()->name() : String();

KURL targetUrl = isLocalDOMWindow() ? document()->url() : KURL(KURL(), frame()->securityContext()->getSecurityOrigin()->toString());
if (MixedContentChecker::isMixedContent(sourceDocument->getSecurityOrigin(), targetUrl))
Expand Down
Loading

0 comments on commit 0233ac7

Please sign in to comment.