Skip to content
This repository was archived by the owner on Jun 24, 2022. It is now read-only.

Commit 6971153

Browse files
Implement W3C Secure Contexts Draft Specification
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 <w3c/webappsec-secure-contexts#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: git-svn-id: http://svn.webkit.org/repository/webkit/trunk@218028 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 6265ef9 commit 6971153

12 files changed

+148
-22
lines changed

Source/WebCore/ChangeLog

+40
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,43 @@
1+
2017-06-09 Daniel Bates <[email protected]>
2+
3+
Implement W3C Secure Contexts Draft Specification
4+
https://bugs.webkit.org/show_bug.cgi?id=158121
5+
<rdar://problem/26012994>
6+
7+
Reviewed by Alex Christensen.
8+
9+
Part 2
10+
11+
Implements the Secure Contexts spec., <https://w3c.github.io/webappsec-secure-contexts/> (Editor's
12+
Draft, 17 November 2016) except for the allow-secure-context sandbox flag and restrictions on window.opener
13+
as the former is at risk of being dropped from the specification and the latter is being discussed in
14+
<https://github.com/w3c/webappsec-secure-contexts/issues/42>. We are not making use of the Secure
15+
Contexts functionality at the moment. We will make use of it in a subsequent commit.
16+
17+
* dom/Document.cpp:
18+
(WebCore::Document::isSecureContext): Added,
19+
* dom/Document.h:
20+
* dom/ScriptExecutionContext.h:
21+
(WebCore::ScriptExecutionContext::isSecureContext): Deleted; moved to class SecurityContext.
22+
* dom/SecurityContext.h:
23+
* page/DOMWindow.cpp:
24+
(WebCore::DOMWindow::isSecureContext): Added.
25+
* page/DOMWindow.h:
26+
* page/SecurityOrigin.cpp:
27+
(WebCore::isLoopbackIPAddress): Convenience function to determine whether the host portion
28+
of the specified URL is a valid loopback address.
29+
(WebCore::shouldTreatAsPotentionallyTrustworthy): Implements the "Is origin potentially trustworthy?"
30+
algorithm from the Secure Context specification.
31+
(WebCore::SecurityOrigin::SecurityOrigin): Compute whether this origin is potentially trustworthy.
32+
Also, use C++ brace initialization syntax in member initialization list.
33+
* page/SecurityOrigin.h:
34+
(WebCore::SecurityOrigin::isPotentionallyTrustworthy): Added.
35+
* page/WindowOrWorkerGlobalScope.idl: Expose attribute isSecureContext. Fix style nit; remove
36+
period from a comment that is not meant to be a complete sentence.
37+
* workers/WorkerGlobalScope.cpp:
38+
(WebCore::WorkerGlobalScope::isSecureContext): Added.
39+
* workers/WorkerGlobalScope.h:
40+
141
2017-06-09 Daniel Bates <[email protected]>
242

343
Implement W3C Secure Contexts Draft Specification

Source/WebCore/dom/Document.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -5321,6 +5321,18 @@ bool Document::isContextThread() const
53215321
return isMainThread();
53225322
}
53235323

5324+
bool Document::isSecureContext() const
5325+
{
5326+
ASSERT(m_frame);
5327+
if (!securityOrigin().isPotentionallyTrustworthy())
5328+
return false;
5329+
for (Frame* frame = m_frame->tree().parent(); frame; frame = frame->tree().parent()) {
5330+
if (!frame->document()->securityOrigin().isPotentionallyTrustworthy())
5331+
return false;
5332+
}
5333+
return true;
5334+
}
5335+
53245336
void Document::updateURLForPushOrReplaceState(const URL& url)
53255337
{
53265338
Frame* f = frame();

Source/WebCore/dom/Document.h

+1
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,7 @@ class Document
10611061
bool loadEventFinished() const { return m_loadEventFinished; }
10621062

10631063
bool isContextThread() const final;
1064+
bool isSecureContext() const final;
10641065
bool isJSExecutionForbidden() const final { return false; }
10651066

10661067
void enqueueWindowEvent(Ref<Event>&&);

Source/WebCore/dom/ScriptExecutionContext.h

-2
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,6 @@ class ScriptExecutionContext : public SecurityContext {
221221

222222
JSC::ExecState* execState();
223223

224-
virtual bool isSecureContext() const { return true; }
225-
226224
protected:
227225
class AddConsoleMessageTask : public Task {
228226
public:

Source/WebCore/dom/SecurityContext.h

+4
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ class SecurityContext {
8585
bool isStrictMixedContentMode() const { return m_isStrictMixedContentMode; }
8686
void setStrictMixedContentMode(bool strictMixedContentMode) { m_isStrictMixedContentMode = strictMixedContentMode; }
8787

88+
// This method implements the "Is the environment settings object settings a secure context?" algorithm from
89+
// the Secure Context spec: https://w3c.github.io/webappsec-secure-contexts/#settings-object (Editor's Draft, 17 November 2016)
90+
virtual bool isSecureContext() const = 0;
91+
8892
protected:
8993
SecurityContext();
9094
virtual ~SecurityContext();

Source/WebCore/page/DOMWindow.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,14 @@ void DOMWindow::cancelAnimationFrame(int id)
17401740
document->cancelAnimationFrame(id);
17411741
}
17421742

1743+
bool DOMWindow::isSecureContext() const
1744+
{
1745+
auto* document = this->document();
1746+
if (!document)
1747+
return false;
1748+
return document->isSecureContext();
1749+
}
1750+
17431751
static void didAddStorageEventListener(DOMWindow& window)
17441752
{
17451753
// Creating these WebCore::Storage objects informs the system that we'd like to receive

Source/WebCore/page/DOMWindow.h

+3
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ class DOMWindow final
247247
int webkitRequestAnimationFrame(Ref<RequestAnimationFrameCallback>&&);
248248
void cancelAnimationFrame(int id);
249249

250+
// Secure Contexts
251+
bool isSecureContext() const;
252+
250253
// Events
251254
// EventTarget API
252255
bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) final;

Source/WebCore/page/SecurityOrigin.cpp

+67-19
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,54 @@ static bool shouldTreatAsUniqueOrigin(const URL& url)
9999
return false;
100100
}
101101

102+
static bool isLoopbackIPAddress(const URL& url)
103+
{
104+
ASSERT(url.isValid());
105+
auto host = url.host();
106+
if (host == "[::1]")
107+
return true;
108+
109+
// Check to see if it's a valid IPv4 address that has the form 127.*.*.*.
110+
if (!host.startsWith("127."))
111+
return false;
112+
size_t dotsFound = 0;
113+
for (size_t i = 0; i < host.length(); ++i) {
114+
if (host[i] == '.') {
115+
dotsFound++;
116+
continue;
117+
}
118+
if (!isASCIIDigit(host[i]))
119+
return false;
120+
}
121+
return dotsFound == 3;
122+
}
123+
124+
// https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy (Editor's Draft, 17 November 2016)
125+
static bool shouldTreatAsPotentionallyTrustworthy(const URL& url)
126+
{
127+
if (!url.isValid())
128+
return false;
129+
130+
if (SchemeRegistry::shouldTreatURLSchemeAsSecure(url.protocol().toStringWithoutCopying()))
131+
return true;
132+
133+
if (isLoopbackIPAddress(url))
134+
return true;
135+
136+
// FIXME: Ensure that localhost resolves to the loopback address.
137+
if (equalLettersIgnoringASCIICase(url.host(), "localhost"))
138+
return true;
139+
140+
if (SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol().toStringWithoutCopying()))
141+
return true;
142+
143+
return false;
144+
}
145+
102146
SecurityOrigin::SecurityOrigin(const URL& url)
103-
: m_protocol(url.protocol().isNull() ? emptyString() : url.protocol().toString().convertToASCIILowercase())
104-
, m_host(url.host().isNull() ? emptyString() : url.host().convertToASCIILowercase())
105-
, m_port(url.port())
147+
: m_protocol { url.protocol().isNull() ? emptyString() : url.protocol().toString().convertToASCIILowercase() }
148+
, m_host { url.host().isNull() ? emptyString() : url.host().convertToASCIILowercase() }
149+
, m_port { url.port() }
106150
{
107151
// document.domain starts as m_host, but can be set by the DOM.
108152
m_domain = m_host;
@@ -115,29 +159,33 @@ SecurityOrigin::SecurityOrigin(const URL& url)
115159

116160
if (m_canLoadLocalResources)
117161
m_filePath = url.fileSystemPath(); // In case enforceFilePathSeparation() is called.
162+
163+
m_isPotentionallyTrustworthy = shouldTreatAsPotentionallyTrustworthy(url);
118164
}
119165

120166
SecurityOrigin::SecurityOrigin()
121-
: m_protocol(emptyString())
122-
, m_host(emptyString())
123-
, m_domain(emptyString())
124-
, m_isUnique(true)
167+
: m_protocol { emptyString() }
168+
, m_host { emptyString() }
169+
, m_domain { emptyString() }
170+
, m_isUnique { true }
171+
, m_isPotentionallyTrustworthy { true }
125172
{
126173
}
127174

128175
SecurityOrigin::SecurityOrigin(const SecurityOrigin* other)
129-
: m_protocol(other->m_protocol.isolatedCopy())
130-
, m_host(other->m_host.isolatedCopy())
131-
, m_domain(other->m_domain.isolatedCopy())
132-
, m_filePath(other->m_filePath.isolatedCopy())
133-
, m_port(other->m_port)
134-
, m_isUnique(other->m_isUnique)
135-
, m_universalAccess(other->m_universalAccess)
136-
, m_domainWasSetInDOM(other->m_domainWasSetInDOM)
137-
, m_canLoadLocalResources(other->m_canLoadLocalResources)
138-
, m_storageBlockingPolicy(other->m_storageBlockingPolicy)
139-
, m_enforceFilePathSeparation(other->m_enforceFilePathSeparation)
140-
, m_needsStorageAccessFromFileURLsQuirk(other->m_needsStorageAccessFromFileURLsQuirk)
176+
: m_protocol { other->m_protocol.isolatedCopy() }
177+
, m_host { other->m_host.isolatedCopy() }
178+
, m_domain { other->m_domain.isolatedCopy() }
179+
, m_filePath { other->m_filePath.isolatedCopy() }
180+
, m_port { other->m_port }
181+
, m_isUnique { other->m_isUnique }
182+
, m_universalAccess { other->m_universalAccess }
183+
, m_domainWasSetInDOM { other->m_domainWasSetInDOM }
184+
, m_canLoadLocalResources { other->m_canLoadLocalResources }
185+
, m_storageBlockingPolicy { other->m_storageBlockingPolicy }
186+
, m_enforceFilePathSeparation { other->m_enforceFilePathSeparation }
187+
, m_needsStorageAccessFromFileURLsQuirk { other->m_needsStorageAccessFromFileURLsQuirk }
188+
, m_isPotentionallyTrustworthy { other->m_isPotentionallyTrustworthy }
141189
{
142190
}
143191

Source/WebCore/page/SecurityOrigin.h

+3
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ class SecurityOrigin : public ThreadSafeRefCounted<SecurityOrigin> {
200200

201201
static URL urlWithUniqueSecurityOrigin();
202202

203+
bool isPotentionallyTrustworthy() const { return m_isPotentionallyTrustworthy; }
204+
203205
private:
204206
SecurityOrigin();
205207
explicit SecurityOrigin(const URL&);
@@ -227,6 +229,7 @@ class SecurityOrigin : public ThreadSafeRefCounted<SecurityOrigin> {
227229
StorageBlockingPolicy m_storageBlockingPolicy { AllowAllStorage };
228230
bool m_enforceFilePathSeparation { false };
229231
bool m_needsStorageAccessFromFileURLsQuirk { false };
232+
bool m_isPotentionallyTrustworthy { false };
230233
};
231234

232235
// Returns true if the Origin header values serialized from these two origins would be the same.

Source/WebCore/page/WindowOrWorkerGlobalScope.idl

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
] interface WindowOrWorkerGlobalScope {
3131
[Replaceable] readonly attribute USVString origin;
3232

33-
// Timers.
33+
// Timers
3434
[Custom] long setTimeout(any handler, optional long timeout = 0);
3535
void clearTimeout(optional long handle = 0);
3636
[Custom] long setInterval(any handler, optional long timeout = 0);
@@ -39,4 +39,7 @@
3939
// Base64 utility methods.
4040
[MayThrowException] DOMString atob(DOMString string);
4141
[MayThrowException] DOMString btoa(DOMString string);
42+
43+
// Secure Contexts
44+
readonly attribute boolean isSecureContext;
4245
};

Source/WebCore/workers/WorkerGlobalScope.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ void WorkerGlobalScope::removeAllEventListeners()
122122
#endif
123123
}
124124

125+
bool WorkerGlobalScope::isSecureContext() const
126+
{
127+
return securityOrigin() && securityOrigin()->isPotentionallyTrustworthy();
128+
}
129+
125130
void WorkerGlobalScope::applyContentSecurityPolicyResponseHeaders(const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders)
126131
{
127132
contentSecurityPolicy()->didReceiveHeaders(contentSecurityPolicyResponseHeaders);

Source/WebCore/workers/WorkerGlobalScope.h

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class WorkerGlobalScope : public RefCounted<WorkerGlobalScope>, public Supplemen
8888
void clearInterval(int timeoutId);
8989

9090
bool isContextThread() const final;
91+
bool isSecureContext() const final;
9192

9293
WorkerNavigator* optionalNavigator() const { return m_navigator.get(); }
9394
WorkerLocation* optionalLocation() const { return m_location.get(); }

0 commit comments

Comments
 (0)