Diff
Modified: trunk/Source/WebCore/ChangeLog (218027 => 218028)
--- trunk/Source/WebCore/ChangeLog 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/ChangeLog 2017-06-09 23:56:46 UTC (rev 218028)
@@ -4,6 +4,46 @@
https://bugs.webkit.org/show_bug.cgi?id=158121
<rdar://problem/26012994>
+ Reviewed by Alex Christensen.
+
+ Part 2
+
+ Implements the Secure Contexts spec., <https://w3c.github.io/webappsec-secure-contexts/> (Editor's
+ Draft, 17 November 2016) except for the allow-secure-context sandbox flag and restrictions on window.opener
+ as the former is at risk of being dropped from the specification and the latter is being discussed in
+ <https://github.com/w3c/webappsec-secure-contexts/issues/42>. We are not making use of the Secure
+ Contexts functionality at the moment. We will make use of it in a subsequent commit.
+
+ * dom/Document.cpp:
+ (WebCore::Document::isSecureContext): Added,
+ * dom/Document.h:
+ * dom/ScriptExecutionContext.h:
+ (WebCore::ScriptExecutionContext::isSecureContext): Deleted; moved to class SecurityContext.
+ * dom/SecurityContext.h:
+ * page/DOMWindow.cpp:
+ (WebCore::DOMWindow::isSecureContext): Added.
+ * page/DOMWindow.h:
+ * page/SecurityOrigin.cpp:
+ (WebCore::isLoopbackIPAddress): Convenience function to determine whether the host portion
+ of the specified URL is a valid loopback address.
+ (WebCore::shouldTreatAsPotentionallyTrustworthy): Implements the "Is origin potentially trustworthy?"
+ algorithm from the Secure Context specification.
+ (WebCore::SecurityOrigin::SecurityOrigin): Compute whether this origin is potentially trustworthy.
+ Also, use C++ brace initialization syntax in member initialization list.
+ * page/SecurityOrigin.h:
+ (WebCore::SecurityOrigin::isPotentionallyTrustworthy): Added.
+ * page/WindowOrWorkerGlobalScope.idl: Expose attribute isSecureContext. Fix style nit; remove
+ period from a comment that is not meant to be a complete sentence.
+ * workers/WorkerGlobalScope.cpp:
+ (WebCore::WorkerGlobalScope::isSecureContext): Added.
+ * workers/WorkerGlobalScope.h:
+
+2017-06-09 Daniel Bates <[email protected]>
+
+ Implement W3C Secure Contexts Draft Specification
+ https://bugs.webkit.org/show_bug.cgi?id=158121
+ <rdar://problem/26012994>
+
Reviewed by Chris Dumez.
Part 1
Modified: trunk/Source/WebCore/dom/Document.cpp (218027 => 218028)
--- trunk/Source/WebCore/dom/Document.cpp 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/dom/Document.cpp 2017-06-09 23:56:46 UTC (rev 218028)
@@ -5321,6 +5321,18 @@
return isMainThread();
}
+bool Document::isSecureContext() const
+{
+ ASSERT(m_frame);
+ if (!securityOrigin().isPotentionallyTrustworthy())
+ return false;
+ for (Frame* frame = m_frame->tree().parent(); frame; frame = frame->tree().parent()) {
+ if (!frame->document()->securityOrigin().isPotentionallyTrustworthy())
+ return false;
+ }
+ return true;
+}
+
void Document::updateURLForPushOrReplaceState(const URL& url)
{
Frame* f = frame();
Modified: trunk/Source/WebCore/dom/Document.h (218027 => 218028)
--- trunk/Source/WebCore/dom/Document.h 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/dom/Document.h 2017-06-09 23:56:46 UTC (rev 218028)
@@ -1061,6 +1061,7 @@
bool loadEventFinished() const { return m_loadEventFinished; }
bool isContextThread() const final;
+ bool isSecureContext() const final;
bool isJSExecutionForbidden() const final { return false; }
void enqueueWindowEvent(Ref<Event>&&);
Modified: trunk/Source/WebCore/dom/ScriptExecutionContext.h (218027 => 218028)
--- trunk/Source/WebCore/dom/ScriptExecutionContext.h 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/dom/ScriptExecutionContext.h 2017-06-09 23:56:46 UTC (rev 218028)
@@ -221,8 +221,6 @@
JSC::ExecState* execState();
- virtual bool isSecureContext() const { return true; }
-
protected:
class AddConsoleMessageTask : public Task {
public:
Modified: trunk/Source/WebCore/dom/SecurityContext.h (218027 => 218028)
--- trunk/Source/WebCore/dom/SecurityContext.h 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/dom/SecurityContext.h 2017-06-09 23:56:46 UTC (rev 218028)
@@ -85,6 +85,10 @@
bool isStrictMixedContentMode() const { return m_isStrictMixedContentMode; }
void setStrictMixedContentMode(bool strictMixedContentMode) { m_isStrictMixedContentMode = strictMixedContentMode; }
+ // This method implements the "Is the environment settings object settings a secure context?" algorithm from
+ // the Secure Context spec: https://w3c.github.io/webappsec-secure-contexts/#settings-object (Editor's Draft, 17 November 2016)
+ virtual bool isSecureContext() const = 0;
+
protected:
SecurityContext();
virtual ~SecurityContext();
Modified: trunk/Source/WebCore/page/DOMWindow.cpp (218027 => 218028)
--- trunk/Source/WebCore/page/DOMWindow.cpp 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/page/DOMWindow.cpp 2017-06-09 23:56:46 UTC (rev 218028)
@@ -1740,6 +1740,14 @@
document->cancelAnimationFrame(id);
}
+bool DOMWindow::isSecureContext() const
+{
+ auto* document = this->document();
+ if (!document)
+ return false;
+ return document->isSecureContext();
+}
+
static void didAddStorageEventListener(DOMWindow& window)
{
// Creating these WebCore::Storage objects informs the system that we'd like to receive
Modified: trunk/Source/WebCore/page/DOMWindow.h (218027 => 218028)
--- trunk/Source/WebCore/page/DOMWindow.h 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/page/DOMWindow.h 2017-06-09 23:56:46 UTC (rev 218028)
@@ -247,6 +247,9 @@
int webkitRequestAnimationFrame(Ref<RequestAnimationFrameCallback>&&);
void cancelAnimationFrame(int id);
+ // Secure Contexts
+ bool isSecureContext() const;
+
// Events
// EventTarget API
bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) final;
Modified: trunk/Source/WebCore/page/SecurityOrigin.cpp (218027 => 218028)
--- trunk/Source/WebCore/page/SecurityOrigin.cpp 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/page/SecurityOrigin.cpp 2017-06-09 23:56:46 UTC (rev 218028)
@@ -99,10 +99,54 @@
return false;
}
+static bool isLoopbackIPAddress(const URL& url)
+{
+ ASSERT(url.isValid());
+ auto host = url.host();
+ if (host == "[::1]")
+ return true;
+
+ // Check to see if it's a valid IPv4 address that has the form 127.*.*.*.
+ if (!host.startsWith("127."))
+ return false;
+ size_t dotsFound = 0;
+ for (size_t i = 0; i < host.length(); ++i) {
+ if (host[i] == '.') {
+ dotsFound++;
+ continue;
+ }
+ if (!isASCIIDigit(host[i]))
+ return false;
+ }
+ return dotsFound == 3;
+}
+
+// https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy (Editor's Draft, 17 November 2016)
+static bool shouldTreatAsPotentionallyTrustworthy(const URL& url)
+{
+ if (!url.isValid())
+ return false;
+
+ if (SchemeRegistry::shouldTreatURLSchemeAsSecure(url.protocol().toStringWithoutCopying()))
+ return true;
+
+ if (isLoopbackIPAddress(url))
+ return true;
+
+ // FIXME: Ensure that localhost resolves to the loopback address.
+ if (equalLettersIgnoringASCIICase(url.host(), "localhost"))
+ return true;
+
+ if (SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol().toStringWithoutCopying()))
+ return true;
+
+ return false;
+}
+
SecurityOrigin::SecurityOrigin(const URL& url)
- : m_protocol(url.protocol().isNull() ? emptyString() : url.protocol().toString().convertToASCIILowercase())
- , m_host(url.host().isNull() ? emptyString() : url.host().convertToASCIILowercase())
- , m_port(url.port())
+ : m_protocol { url.protocol().isNull() ? emptyString() : url.protocol().toString().convertToASCIILowercase() }
+ , m_host { url.host().isNull() ? emptyString() : url.host().convertToASCIILowercase() }
+ , m_port { url.port() }
{
// document.domain starts as m_host, but can be set by the DOM.
m_domain = m_host;
@@ -115,29 +159,33 @@
if (m_canLoadLocalResources)
m_filePath = url.fileSystemPath(); // In case enforceFilePathSeparation() is called.
+
+ m_isPotentionallyTrustworthy = shouldTreatAsPotentionallyTrustworthy(url);
}
SecurityOrigin::SecurityOrigin()
- : m_protocol(emptyString())
- , m_host(emptyString())
- , m_domain(emptyString())
- , m_isUnique(true)
+ : m_protocol { emptyString() }
+ , m_host { emptyString() }
+ , m_domain { emptyString() }
+ , m_isUnique { true }
+ , m_isPotentionallyTrustworthy { true }
{
}
SecurityOrigin::SecurityOrigin(const SecurityOrigin* other)
- : m_protocol(other->m_protocol.isolatedCopy())
- , m_host(other->m_host.isolatedCopy())
- , m_domain(other->m_domain.isolatedCopy())
- , m_filePath(other->m_filePath.isolatedCopy())
- , m_port(other->m_port)
- , m_isUnique(other->m_isUnique)
- , m_universalAccess(other->m_universalAccess)
- , m_domainWasSetInDOM(other->m_domainWasSetInDOM)
- , m_canLoadLocalResources(other->m_canLoadLocalResources)
- , m_storageBlockingPolicy(other->m_storageBlockingPolicy)
- , m_enforceFilePathSeparation(other->m_enforceFilePathSeparation)
- , m_needsStorageAccessFromFileURLsQuirk(other->m_needsStorageAccessFromFileURLsQuirk)
+ : m_protocol { other->m_protocol.isolatedCopy() }
+ , m_host { other->m_host.isolatedCopy() }
+ , m_domain { other->m_domain.isolatedCopy() }
+ , m_filePath { other->m_filePath.isolatedCopy() }
+ , m_port { other->m_port }
+ , m_isUnique { other->m_isUnique }
+ , m_universalAccess { other->m_universalAccess }
+ , m_domainWasSetInDOM { other->m_domainWasSetInDOM }
+ , m_canLoadLocalResources { other->m_canLoadLocalResources }
+ , m_storageBlockingPolicy { other->m_storageBlockingPolicy }
+ , m_enforceFilePathSeparation { other->m_enforceFilePathSeparation }
+ , m_needsStorageAccessFromFileURLsQuirk { other->m_needsStorageAccessFromFileURLsQuirk }
+ , m_isPotentionallyTrustworthy { other->m_isPotentionallyTrustworthy }
{
}
Modified: trunk/Source/WebCore/page/SecurityOrigin.h (218027 => 218028)
--- trunk/Source/WebCore/page/SecurityOrigin.h 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/page/SecurityOrigin.h 2017-06-09 23:56:46 UTC (rev 218028)
@@ -200,6 +200,8 @@
static URL urlWithUniqueSecurityOrigin();
+ bool isPotentionallyTrustworthy() const { return m_isPotentionallyTrustworthy; }
+
private:
SecurityOrigin();
explicit SecurityOrigin(const URL&);
@@ -227,6 +229,7 @@
StorageBlockingPolicy m_storageBlockingPolicy { AllowAllStorage };
bool m_enforceFilePathSeparation { false };
bool m_needsStorageAccessFromFileURLsQuirk { false };
+ bool m_isPotentionallyTrustworthy { false };
};
// Returns true if the Origin header values serialized from these two origins would be the same.
Modified: trunk/Source/WebCore/page/WindowOrWorkerGlobalScope.idl (218027 => 218028)
--- trunk/Source/WebCore/page/WindowOrWorkerGlobalScope.idl 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/page/WindowOrWorkerGlobalScope.idl 2017-06-09 23:56:46 UTC (rev 218028)
@@ -30,7 +30,7 @@
] interface WindowOrWorkerGlobalScope {
[Replaceable] readonly attribute USVString origin;
- // Timers.
+ // Timers
[Custom] long setTimeout(any handler, optional long timeout = 0);
void clearTimeout(optional long handle = 0);
[Custom] long setInterval(any handler, optional long timeout = 0);
@@ -39,4 +39,7 @@
// Base64 utility methods.
[MayThrowException] DOMString atob(DOMString string);
[MayThrowException] DOMString btoa(DOMString string);
+
+ // Secure Contexts
+ readonly attribute boolean isSecureContext;
};
Modified: trunk/Source/WebCore/workers/WorkerGlobalScope.cpp (218027 => 218028)
--- trunk/Source/WebCore/workers/WorkerGlobalScope.cpp 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/workers/WorkerGlobalScope.cpp 2017-06-09 23:56:46 UTC (rev 218028)
@@ -122,6 +122,11 @@
#endif
}
+bool WorkerGlobalScope::isSecureContext() const
+{
+ return securityOrigin() && securityOrigin()->isPotentionallyTrustworthy();
+}
+
void WorkerGlobalScope::applyContentSecurityPolicyResponseHeaders(const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders)
{
contentSecurityPolicy()->didReceiveHeaders(contentSecurityPolicyResponseHeaders);
Modified: trunk/Source/WebCore/workers/WorkerGlobalScope.h (218027 => 218028)
--- trunk/Source/WebCore/workers/WorkerGlobalScope.h 2017-06-09 23:38:05 UTC (rev 218027)
+++ trunk/Source/WebCore/workers/WorkerGlobalScope.h 2017-06-09 23:56:46 UTC (rev 218028)
@@ -88,6 +88,7 @@
void clearInterval(int timeoutId);
bool isContextThread() const final;
+ bool isSecureContext() const final;
WorkerNavigator* optionalNavigator() const { return m_navigator.get(); }
WorkerLocation* optionalLocation() const { return m_location.get(); }