[iOS] Further tighten the sandbox around pages fetched with Content-Disposition:...
authoraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 18 Jul 2015 03:47:28 +0000 (03:47 +0000)
committeraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 18 Jul 2015 03:47:28 +0000 (03:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=147044
rdar://problem/21567820

Reviewed by Brady Eidson.

Source/WebCore:

In addition to placing resources fetched with 'Content-Disposition: attachment' in a unique origin,
this change does the following:

- Switches the sandbox type from SandboxOrigin to SandboxAll, which enforces the same restrictions as <iframe sandbox>.
- Disables processing of <meta http-equiv> elements.
- Disables loading of cross-origin subframes.

Tests: http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled.html
       http/tests/contentdispositionattachmentsandbox/form-submission-disabled.html
       http/tests/contentdispositionattachmentsandbox/http-equiv-disabled.html
       http/tests/contentdispositionattachmentsandbox/plugins-disabled.html
       http/tests/contentdispositionattachmentsandbox/scripts-disabled.html

* dom/Document.cpp:
(WebCore::Document::processHttpEquiv): Switched to calling Document::httpEquivPolicy(). Logged an error to the console for policies other than Enabled.
(WebCore::Document::initSecurityContext): Switched sandbox enforcement from SandboxOrigin to SandboxAll.
(WebCore::Document::httpEquivPolicy): Returned a HttpEquivPolicy based on shouldEnforceContentDispositionAttachmentSandbox() and Settings::httpEquivEnabled().
(WebCore::Document::shouldEnforceContentDispositionAttachmentSandbox): Returned true if Settings::contentDispositionAttachmentSandboxEnabled()
and the document was fetched as an attachment.
* dom/Document.h:
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::canRequest): When requesting a subframe main resource when the parent frame enforces an attachment sandbox,
only continue if the parent frame's SecurityOrigin allows the request.
* page/Settings.in: Added contentDispositionAttachmentSandboxEnabled with an initial value of false.

Source/WebKit/mac:

* WebView/WebView.mm:
(-[WebView _commonInitializationWithFrameName:groupName:]): Enabled Content-Disposition: attachment sandbox on iOS.

Source/WebKit2:

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::WebPage): Enabled Content-Disposition: attachment sandbox on iOS.

Tools:

* WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
(WTR::InjectedBundlePage::decidePolicyForResponse): Only log the message about attachments if the custom policy delegate is enabled.
This matches the behavior of DumpRenderTree.

LayoutTests:

* http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled-expected.txt: Added.
* http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled.html: Added.
* http/tests/contentdispositionattachmentsandbox/form-submission-disabled-expected.txt: Added.
* http/tests/contentdispositionattachmentsandbox/form-submission-disabled.html: Added.
* http/tests/contentdispositionattachmentsandbox/http-equiv-disabled-expected.txt: Added.
* http/tests/contentdispositionattachmentsandbox/http-equiv-disabled.html: Added.
* http/tests/contentdispositionattachmentsandbox/plugins-disabled-expected.html: Added.
* http/tests/contentdispositionattachmentsandbox/plugins-disabled.html: Added.
* http/tests/contentdispositionattachmentsandbox/resources/cross-origin-frames-frame.php: Added.
* http/tests/contentdispositionattachmentsandbox/resources/form-submission-frame.php: Added.
* http/tests/contentdispositionattachmentsandbox/resources/http-equiv-frame.php: Added.
* http/tests/contentdispositionattachmentsandbox/resources/plugins-frame.php: Added.
* http/tests/contentdispositionattachmentsandbox/resources/scripts-frame.php: Added.
* http/tests/contentdispositionattachmentsandbox/scripts-disabled-expected.txt: Added.
* http/tests/contentdispositionattachmentsandbox/scripts-disabled.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@186982 268f45cc-cd09-0410-ab3c-d52691b4dbfc

27 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled.html [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/form-submission-disabled-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/form-submission-disabled.html [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/http-equiv-disabled-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/http-equiv-disabled.html [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/plugins-disabled-expected.html [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/plugins-disabled.html [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/cross-origin-frames-frame.php [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/form-submission-frame.php [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/http-equiv-frame.php [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/plugins-frame.php [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/scripts-frame.php [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/scripts-disabled-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/contentdispositionattachmentsandbox/scripts-disabled.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/loader/cache/CachedResourceLoader.cpp
Source/WebCore/page/Settings.in
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebView/WebView.mm
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Tools/ChangeLog
Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp

index 3457f23..d1855f5 100644 (file)
@@ -1,3 +1,27 @@
+2015-07-17  Andy Estes  <aestes@apple.com>
+
+        [iOS] Further tighten the sandbox around pages fetched with Content-Disposition: attachment
+        https://bugs.webkit.org/show_bug.cgi?id=147044
+        rdar://problem/21567820
+
+        Reviewed by Brady Eidson.
+
+        * http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled-expected.txt: Added.
+        * http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled.html: Added.
+        * http/tests/contentdispositionattachmentsandbox/form-submission-disabled-expected.txt: Added.
+        * http/tests/contentdispositionattachmentsandbox/form-submission-disabled.html: Added.
+        * http/tests/contentdispositionattachmentsandbox/http-equiv-disabled-expected.txt: Added.
+        * http/tests/contentdispositionattachmentsandbox/http-equiv-disabled.html: Added.
+        * http/tests/contentdispositionattachmentsandbox/plugins-disabled-expected.html: Added.
+        * http/tests/contentdispositionattachmentsandbox/plugins-disabled.html: Added.
+        * http/tests/contentdispositionattachmentsandbox/resources/cross-origin-frames-frame.php: Added.
+        * http/tests/contentdispositionattachmentsandbox/resources/form-submission-frame.php: Added.
+        * http/tests/contentdispositionattachmentsandbox/resources/http-equiv-frame.php: Added.
+        * http/tests/contentdispositionattachmentsandbox/resources/plugins-frame.php: Added.
+        * http/tests/contentdispositionattachmentsandbox/resources/scripts-frame.php: Added.
+        * http/tests/contentdispositionattachmentsandbox/scripts-disabled-expected.txt: Added.
+        * http/tests/contentdispositionattachmentsandbox/scripts-disabled.html: Added.
+
 2015-07-17  Zalan Bujtas  <zalan@apple.com>
 
         (display: block)input range's thumb disappears when moved.
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled-expected.txt b/LayoutTests/http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled-expected.txt
new file mode 100644 (file)
index 0000000..2ab56db
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Unsafe attempt to load URL data:text/html,FAIL.
+This test verifies that cross-origin frames are disabled when 'Content-Disposition: attachment' sandboxing is enabled. A security error will be logged to the console if the test passes.
+
+
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled.html b/LayoutTests/http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled.html
new file mode 100644 (file)
index 0000000..9cb144a
--- /dev/null
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.settings.setContentDispositionAttachmentSandboxEnabled(true);
+</script>
+<p>This test verifies that cross-origin frames are disabled when 'Content-Disposition: attachment' sandboxing is enabled. A security error will be logged to the console if the test passes.</p>
+<iframe src="resources/cross-origin-frames-frame.php"></iframe>
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/form-submission-disabled-expected.txt b/LayoutTests/http/tests/contentdispositionattachmentsandbox/form-submission-disabled-expected.txt
new file mode 100644 (file)
index 0000000..2ec7869
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: line 21: Blocked form submission to 'http://127.0.0.1:8000/contentdispositionattachmentsandbox/resources/form-submission-frame.php' because the form's frame is sandboxed and the 'allow-forms' permission is not set.
+This test verifies that form submission is disabled when 'Content-Disposition: attachment' sandboxing is enabled. A security error will be logged to the console if the test passes.
+
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/form-submission-disabled.html b/LayoutTests/http/tests/contentdispositionattachmentsandbox/form-submission-disabled.html
new file mode 100644 (file)
index 0000000..bc0fdeb
--- /dev/null
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<script>
+if (window.internals)
+    internals.settings.setContentDispositionAttachmentSandboxEnabled(true);
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+    window.addEventListener('load', function() {
+        // Due to the sandbox, it's not possible to run script in the iframe or even access its contentDocument.
+        // Submit the form by clicking its button with synthetic mouse events.
+        var iframeRect = document.getElementsByTagName('iframe')[0].getClientRects()[0];
+        var submitButtonRect = document.getElementById('submitButtonForMetrics').getClientRects()[0];
+        
+        // This assumes that the iframe has no border, and its document's body has no margin.
+        var x = iframeRect.left + submitButtonRect.width / 2;
+        var y = iframeRect.top + submitButtonRect.height / 2;
+
+        eventSender.mouseMoveTo(x, y);
+        eventSender.mouseDown();
+        eventSender.mouseUp();
+        testRunner.notifyDone();
+    });
+}
+</script>
+<p>This test verifies that form submission is disabled when 'Content-Disposition: attachment' sandboxing is enabled. A security error will be logged to the console if the test passes.</p>
+<iframe style="border: 0px" src="resources/form-submission-frame.php"></iframe>
+<input style="visibility: hidden" id="submitButtonForMetrics" type="submit">
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/http-equiv-disabled-expected.txt b/LayoutTests/http/tests/contentdispositionattachmentsandbox/http-equiv-disabled-expected.txt
new file mode 100644 (file)
index 0000000..db12105
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: line 2: http-equiv 'refresh' is disabled for documents with Content-Disposition: attachment.
+This test verifies that <meta http-equiv> processing is disabled when 'Content-Disposition: attachment' sandboxing is enabled. A security error will be logged to the console if the test passes.
+
+
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/http-equiv-disabled.html b/LayoutTests/http/tests/contentdispositionattachmentsandbox/http-equiv-disabled.html
new file mode 100644 (file)
index 0000000..2ad8f49
--- /dev/null
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.settings.setContentDispositionAttachmentSandboxEnabled(true);
+</script>
+<p>This test verifies that &lt;meta http-equiv&gt; processing is disabled when 'Content-Disposition: attachment' sandboxing is enabled. A security error will be logged to the console if the test passes.</p>
+<iframe src="resources/http-equiv-frame.php"></iframe>
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/plugins-disabled-expected.html b/LayoutTests/http/tests/contentdispositionattachmentsandbox/plugins-disabled-expected.html
new file mode 100644 (file)
index 0000000..664003b
--- /dev/null
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<p>This test verifies that plug-ins are disabled when 'Content-Disposition: attachment' sandboxing is enabled. 'PASS' is displayed in the &lt;iframe&gt; below if the test passes.</p>
+<iframe srcdoc="<!DOCTYPE html>PASS"></iframe>
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/plugins-disabled.html b/LayoutTests/http/tests/contentdispositionattachmentsandbox/plugins-disabled.html
new file mode 100644 (file)
index 0000000..c2af527
--- /dev/null
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<script>
+if (window.internals)
+    internals.settings.setContentDispositionAttachmentSandboxEnabled(true);
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+
+    // The doubly-nested setTimeout() is meant to account for two timers in the object fallback content rendering process.
+    // We can't rely on object's onerror event since we cannot run script in the sandboxed frame, so we must wait for the
+    // post-layout timer followed by the embedded objects update timer to ensure that fallback content has been rendered.
+    window.addEventListener('load', function() {
+        window.setTimeout(function() {
+            window.setTimeout(function() {
+                testRunner.notifyDone();
+            }, 0);
+        }, 0);
+    });
+}
+</script>
+<p>This test verifies that plug-ins are disabled when 'Content-Disposition: attachment' sandboxing is enabled. 'PASS' is displayed in the &lt;iframe&gt; below if the test passes.</p>
+<iframe src="resources/plugins-frame.php"></iframe>
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/cross-origin-frames-frame.php b/LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/cross-origin-frames-frame.php
new file mode 100644 (file)
index 0000000..7a19174
--- /dev/null
@@ -0,0 +1,6 @@
+<?php
+header("Content-Disposition: attachment; filename=test.html");
+header("Content-Type: text/html");
+?>
+<!DOCTYPE html>
+<iframe src="data:text/html,FAIL"></iframe>
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/form-submission-frame.php b/LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/form-submission-frame.php
new file mode 100644 (file)
index 0000000..89f07bd
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+header("Content-Disposition: attachment; filename=test.html");
+header("Content-Type: text/html");
+?>
+<!DOCTYPE html>
+<style>
+body {
+    margin: 0px;
+}
+</style>
+<form>
+<input type="submit">
+</form>
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/http-equiv-frame.php b/LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/http-equiv-frame.php
new file mode 100644 (file)
index 0000000..67567d9
--- /dev/null
@@ -0,0 +1,6 @@
+<?php
+header("Content-Disposition: attachment; filename=test.html");
+header("Content-Type: text/html");
+?>
+<!DOCTYPE html>
+<meta http-equiv="refresh" content="0; url=data:text/html,FAIL">
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/plugins-frame.php b/LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/plugins-frame.php
new file mode 100644 (file)
index 0000000..8bdccb8
--- /dev/null
@@ -0,0 +1,6 @@
+<?php
+header("Content-Disposition: attachment; filename=test.html");
+header("Content-Type: text/html");
+?>
+<!DOCTYPE html>
+<object type="application/x-webkit-test-netscape">PASS</object>
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/scripts-frame.php b/LayoutTests/http/tests/contentdispositionattachmentsandbox/resources/scripts-frame.php
new file mode 100644 (file)
index 0000000..1067500
--- /dev/null
@@ -0,0 +1,8 @@
+<?php
+header("Content-Disposition: attachment; filename=test.html");
+header("Content-Type: text/html");
+?>
+<!DOCTYPE html>
+<script>
+document.write('FAIL');
+</script>
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/scripts-disabled-expected.txt b/LayoutTests/http/tests/contentdispositionattachmentsandbox/scripts-disabled-expected.txt
new file mode 100644 (file)
index 0000000..1d49f41
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Blocked script execution in 'http://127.0.0.1:8000/contentdispositionattachmentsandbox/resources/scripts-frame.php' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.
+This test verifies that scripts are disabled when 'Content-Disposition: attachment' sandboxing is enabled. A security error will be logged to the console if the test passes.
+
+
diff --git a/LayoutTests/http/tests/contentdispositionattachmentsandbox/scripts-disabled.html b/LayoutTests/http/tests/contentdispositionattachmentsandbox/scripts-disabled.html
new file mode 100644 (file)
index 0000000..0ed5475
--- /dev/null
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+if (window.internals)
+    internals.settings.setContentDispositionAttachmentSandboxEnabled(true);
+</script>
+<p>This test verifies that scripts are disabled when 'Content-Disposition: attachment' sandboxing is enabled. A security error will be logged to the console if the test passes.</p>
+<iframe src="resources/scripts-frame.php"></iframe>
index f93cbec..6ab7f60 100644 (file)
@@ -1,3 +1,36 @@
+2015-07-17  Andy Estes  <aestes@apple.com>
+
+        [iOS] Further tighten the sandbox around pages fetched with Content-Disposition: attachment
+        https://bugs.webkit.org/show_bug.cgi?id=147044
+        rdar://problem/21567820
+
+        Reviewed by Brady Eidson.
+
+        In addition to placing resources fetched with 'Content-Disposition: attachment' in a unique origin,
+        this change does the following:
+
+        - Switches the sandbox type from SandboxOrigin to SandboxAll, which enforces the same restrictions as <iframe sandbox>.
+        - Disables processing of <meta http-equiv> elements.
+        - Disables loading of cross-origin subframes.
+
+        Tests: http/tests/contentdispositionattachmentsandbox/cross-origin-frames-disabled.html
+               http/tests/contentdispositionattachmentsandbox/form-submission-disabled.html
+               http/tests/contentdispositionattachmentsandbox/http-equiv-disabled.html
+               http/tests/contentdispositionattachmentsandbox/plugins-disabled.html
+               http/tests/contentdispositionattachmentsandbox/scripts-disabled.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::processHttpEquiv): Switched to calling Document::httpEquivPolicy(). Logged an error to the console for policies other than Enabled.
+        (WebCore::Document::initSecurityContext): Switched sandbox enforcement from SandboxOrigin to SandboxAll.
+        (WebCore::Document::httpEquivPolicy): Returned a HttpEquivPolicy based on shouldEnforceContentDispositionAttachmentSandbox() and Settings::httpEquivEnabled().
+        (WebCore::Document::shouldEnforceContentDispositionAttachmentSandbox): Returned true if Settings::contentDispositionAttachmentSandboxEnabled()
+        and the document was fetched as an attachment.
+        * dom/Document.h:
+        * loader/cache/CachedResourceLoader.cpp: 
+        (WebCore::CachedResourceLoader::canRequest): When requesting a subframe main resource when the parent frame enforces an attachment sandbox,
+        only continue if the parent frame's SecurityOrigin allows the request.
+        * page/Settings.in: Added contentDispositionAttachmentSandboxEnabled with an initial value of false.
+
 2015-07-17  Zalan Bujtas  <zalan@apple.com>
 
         (display: block)input range's thumb disappears when moved.
index 445784b..8ee4939 100644 (file)
@@ -3026,8 +3026,24 @@ void Document::processHttpEquiv(const String& equiv, const String& content)
 {
     ASSERT(!equiv.isNull() && !content.isNull());
 
-    if (page() && !page()->settings().httpEquivEnabled())
+    HttpEquivPolicy policy = httpEquivPolicy();
+    if (policy != HttpEquivPolicy::Enabled) {
+        String reason;
+        switch (policy) {
+        case HttpEquivPolicy::Enabled:
+            ASSERT_NOT_REACHED();
+            break;
+        case HttpEquivPolicy::DisabledBySettings:
+            reason = "by the embedder.";
+            break;
+        case HttpEquivPolicy::DisabledByContentDispositionAttachmentSandbox:
+            reason = "for documents with Content-Disposition: attachment.";
+            break;
+        }
+        String message = "http-equiv '" + equiv + "' is disabled " + reason;
+        addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
         return;
+    }
 
     Frame* frame = this->frame();
 
@@ -4895,15 +4911,8 @@ void Document::initSecurityContext()
     setCookieURL(m_url);
     enforceSandboxFlags(m_frame->loader().effectiveSandboxFlags());
 
-#if PLATFORM(IOS)
-    // On iOS we display attachments inline regardless of whether the response includes
-    // the HTTP header "Content-Disposition: attachment". So, we enforce a unique
-    // security origin for such documents. As an optimization, we don't need to parse
-    // the responde header (i.e. call ResourceResponse::isAttachment()) for a synthesized
-    // document because such documents cannot be an attachment.
-    if (!m_isSynthesized && m_frame->loader().activeDocumentLoader()->response().isAttachment())
-        enforceSandboxFlags(SandboxOrigin);
-#endif
+    if (shouldEnforceContentDispositionAttachmentSandbox())
+        enforceSandboxFlags(SandboxAll);
 
     setSecurityOriginPolicy(SecurityOriginPolicy::create(isSandboxed(SandboxOrigin) ? SecurityOrigin::createUnique() : SecurityOrigin::create(m_url)));
     setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(this));
@@ -6002,6 +6011,15 @@ void Document::didAddWheelEventHandler(Node& node)
         DebugPageOverlays::didChangeEventHandlers(*frame);
 }
 
+HttpEquivPolicy Document::httpEquivPolicy() const
+{
+    if (shouldEnforceContentDispositionAttachmentSandbox())
+        return HttpEquivPolicy::DisabledByContentDispositionAttachmentSandbox;
+    if (page() && !page()->settings().httpEquivEnabled())
+        return HttpEquivPolicy::DisabledBySettings;
+    return HttpEquivPolicy::Enabled;
+}
+
 static bool removeHandlerFromSet(EventTargetSet& handlerSet, Node& node, EventHandlerRemoval removal)
 {
     switch (removal) {
@@ -6675,4 +6693,17 @@ ShouldOpenExternalURLsPolicy Document::shouldOpenExternalURLsPolicyToPropagate()
     return ShouldOpenExternalURLsPolicy::ShouldNotAllow;
 }
 
+bool Document::shouldEnforceContentDispositionAttachmentSandbox() const
+{
+    if (m_isSynthesized)
+        return false;
+
+    bool contentDispositionAttachmentSandboxEnabled = settings() && settings()->contentDispositionAttachmentSandboxEnabled();
+    bool responseIsAttachment = false;
+    if (DocumentLoader* documentLoader = m_frame ? m_frame->loader().activeDocumentLoader() : nullptr)
+        responseIsAttachment = documentLoader->response().isAttachment();
+
+    return contentDispositionAttachmentSandboxEnabled && responseIsAttachment;
+}
+
 } // namespace WebCore
index 4299159..e5c082f 100644 (file)
@@ -269,6 +269,12 @@ enum class DocumentCompatibilityMode : unsigned char {
 
 enum DimensionsCheck { WidthDimensionsCheck = 1 << 0, HeightDimensionsCheck = 1 << 1, AllDimensionsCheck = 1 << 2 };
 
+enum class HttpEquivPolicy {
+    Enabled,
+    DisabledBySettings,
+    DisabledByContentDispositionAttachmentSandbox
+};
+
 class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext, public FontSelectorClient {
 public:
     static Ref<Document> create(Frame* frame, const URL& url)
@@ -1265,6 +1271,7 @@ public:
 #endif
 
     ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToPropagate() const;
+    bool shouldEnforceContentDispositionAttachmentSandbox() const;
 
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
@@ -1350,6 +1357,8 @@ private:
 
     void wheelEventHandlersChanged();
 
+    HttpEquivPolicy httpEquivPolicy() const;
+
     // DOM Cookies caching.
     const String& cachedDOMCookies() const { return m_cachedDOMCookies; }
     void setCachedDOMCookies(const String&);
index 059163b..8fc9d73 100644 (file)
@@ -373,6 +373,13 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const URL& url,
     // any URL.
     switch (type) {
     case CachedResource::MainResource:
+        if (HTMLFrameOwnerElement* ownerElement = frame() ? frame()->ownerElement() : nullptr) {
+            if (ownerElement->document().shouldEnforceContentDispositionAttachmentSandbox() && !ownerElement->document().securityOrigin()->canRequest(url)) {
+                printAccessDeniedMessage(url);
+                return false;
+            }
+        }
+        FALLTHROUGH;
     case CachedResource::ImageResource:
     case CachedResource::CSSStyleSheet:
     case CachedResource::Script:
index 127ae96..39af718 100644 (file)
@@ -243,3 +243,9 @@ attachmentElementEnabled initial=true, conditional=ATTACHMENT_ELEMENT
 newBlockInsideInlineModelEnabled initial=false, setNeedsStyleRecalcInAllFrames=1
 
 httpEquivEnabled initial=true
+
+# Some ports (e.g. iOS) might choose to display attachments inline, regardless of whether the response includes the
+# HTTP header "Content-Disposition: attachment". This setting enables a sandbox around these attachments. The sandbox
+# enforces all frame sandbox flags (see enum SandboxFlag in SecurityContext.h), and also disables <meta http-equiv>
+# processing and subframe loading.
+contentDispositionAttachmentSandboxEnabled initial=false
index 2ddf4e2..a48e514 100644 (file)
@@ -1,3 +1,14 @@
+2015-07-17  Andy Estes  <aestes@apple.com>
+
+        [iOS] Further tighten the sandbox around pages fetched with Content-Disposition: attachment
+        https://bugs.webkit.org/show_bug.cgi?id=147044
+        rdar://problem/21567820
+
+        Reviewed by Brady Eidson.
+
+        * WebView/WebView.mm:
+        (-[WebView _commonInitializationWithFrameName:groupName:]): Enabled Content-Disposition: attachment sandbox on iOS.
+
 2015-07-16  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: [Mac] Save dialog not working when inspector is docked
index 9cb5845..6419ddc 100644 (file)
@@ -1085,6 +1085,10 @@ static void WebKitInitializeGamepadProviderIfNecessary()
 
     _private->page->setDeviceScaleFactor([self _deviceScaleFactor]);
 #endif
+
+#if PLATFORM(IOS)
+    _private->page->settings().setContentDispositionAttachmentSandboxEnabled(true);
+#endif
 }
 
 - (id)_initWithFrame:(NSRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName
index 91c1475..c025867 100644 (file)
@@ -1,3 +1,14 @@
+2015-07-17  Andy Estes  <aestes@apple.com>
+
+        [iOS] Further tighten the sandbox around pages fetched with Content-Disposition: attachment
+        https://bugs.webkit.org/show_bug.cgi?id=147044
+        rdar://problem/21567820
+
+        Reviewed by Brady Eidson.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::WebPage): Enabled Content-Disposition: attachment sandbox on iOS.
+
 2015-07-17  Tim Horton  <timothy_horton@apple.com>
 
         [iOS] TextIndicator has a large forehead when line-height > 1
index e910ab5..1202719 100644 (file)
@@ -519,6 +519,10 @@ WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
         scaleView(parameters.viewScaleFactor);
 
     m_page->setUserContentExtensionsEnabled(parameters.userContentExtensionsEnabled);
+
+#if PLATFORM(IOS)
+    m_page->settings().setContentDispositionAttachmentSandboxEnabled(true);
+#endif
 }
 
 void WebPage::reinitializeWebPage(const WebPageCreationParameters& parameters)
index 0e3a4ad..653bf2b 100644 (file)
@@ -1,3 +1,15 @@
+2015-07-17  Andy Estes  <aestes@apple.com>
+
+        [iOS] Further tighten the sandbox around pages fetched with Content-Disposition: attachment
+        https://bugs.webkit.org/show_bug.cgi?id=147044
+        rdar://problem/21567820
+
+        Reviewed by Brady Eidson.
+
+        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
+        (WTR::InjectedBundlePage::decidePolicyForResponse): Only log the message about attachments if the custom policy delegate is enabled.
+        This matches the behavior of DumpRenderTree.
+
 2015-07-17  Benjamin Poulain  <bpoulain@apple.com>
 
         [Content Extensions] Term::isUniversalTransition() incorrectly expects the end-of-line assertion in character sets
index 538d7e8..9d232ee 100644 (file)
@@ -1326,7 +1326,7 @@ WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForNewWindowAction(WKBu
 
 WKBundlePagePolicyAction InjectedBundlePage::decidePolicyForResponse(WKBundlePageRef page, WKBundleFrameRef, WKURLResponseRef response, WKURLRequestRef, WKTypeRef*)
 {
-    if (WKURLResponseIsAttachment(response)) {
+    if (InjectedBundle::singleton().testRunner()->isPolicyDelegateEnabled() && WKURLResponseIsAttachment(response)) {
         StringBuilder stringBuilder;
         WKRetainPtr<WKStringRef> filename = adoptWK(WKURLResponseCopySuggestedFilename(response));
         stringBuilder.appendLiteral("Policy delegate: resource is an attachment, suggested file name \'");