Introduce Storage Access API (document parts) as an experimental feature
[WebKit-https.git] / Source / WebCore / dom / SecurityContext.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26
27 #include "config.h"
28 #include "SecurityContext.h"
29
30 #include "ContentSecurityPolicy.h"
31 #include "HTMLParserIdioms.h"
32 #include "SecurityOrigin.h"
33 #include "SecurityOriginPolicy.h"
34 #include <wtf/text/StringBuilder.h>
35
36 namespace WebCore {
37
38 SecurityContext::SecurityContext()
39 {
40 }
41
42 SecurityContext::~SecurityContext()
43 {
44 }
45
46 void SecurityContext::setSecurityOriginPolicy(RefPtr<SecurityOriginPolicy>&& securityOriginPolicy)
47 {
48     m_securityOriginPolicy = WTFMove(securityOriginPolicy);
49     m_haveInitializedSecurityOrigin = true;
50 }
51
52 SecurityOrigin* SecurityContext::securityOrigin() const
53 {
54     if (!m_securityOriginPolicy)
55         return nullptr;
56
57     return &m_securityOriginPolicy->origin();
58 }
59
60 void SecurityContext::setContentSecurityPolicy(std::unique_ptr<ContentSecurityPolicy> contentSecurityPolicy)
61 {
62     m_contentSecurityPolicy = WTFMove(contentSecurityPolicy);
63 }
64
65 bool SecurityContext::isSecureTransitionTo(const URL& url) const
66 {
67     // If we haven't initialized our security origin by now, this is probably
68     // a new window created via the API (i.e., that lacks an origin and lacks
69     // a place to inherit the origin from).
70     if (!haveInitializedSecurityOrigin())
71         return true;
72
73     return securityOriginPolicy()->origin().canAccess(SecurityOrigin::create(url).get());
74 }
75
76 void SecurityContext::enforceSandboxFlags(SandboxFlags mask)
77 {
78     m_sandboxFlags |= mask;
79
80     // The SandboxOrigin is stored redundantly in the security origin.
81     if (isSandboxed(SandboxOrigin) && securityOriginPolicy() && !securityOriginPolicy()->origin().isUnique())
82         setSecurityOriginPolicy(SecurityOriginPolicy::create(SecurityOrigin::createUnique()));
83 }
84
85 bool SecurityContext::isSupportedSandboxPolicy(StringView policy)
86 {
87     static const char* const supportedPolicies[] = {
88         "allow-forms", "allow-same-origin", "allow-scripts", "allow-top-navigation", "allow-pointer-lock", "allow-popups", "allow-popups-to-escape-sandbox", "allow-top-navigation-by-user-activation", "allow-modals", "allow-storage-access-by-user-activation"
89     };
90
91     for (auto* supportedPolicy : supportedPolicies) {
92         if (equalIgnoringASCIICase(policy, supportedPolicy))
93             return true;
94     }
95     return false;
96 }
97
98 // Keep SecurityContext::isSupportedSandboxPolicy() in sync when updating this function.
99 SandboxFlags SecurityContext::parseSandboxPolicy(const String& policy, String& invalidTokensErrorMessage)
100 {
101     // http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
102     // Parse the unordered set of unique space-separated tokens.
103     SandboxFlags flags = SandboxAll;
104     unsigned length = policy.length();
105     unsigned start = 0;
106     unsigned numberOfTokenErrors = 0;
107     StringBuilder tokenErrors;
108     while (true) {
109         while (start < length && isHTMLSpace(policy[start]))
110             ++start;
111         if (start >= length)
112             break;
113         unsigned end = start + 1;
114         while (end < length && !isHTMLSpace(policy[end]))
115             ++end;
116
117         // Turn off the corresponding sandbox flag if it's set as "allowed".
118         String sandboxToken = policy.substring(start, end - start);
119         if (equalLettersIgnoringASCIICase(sandboxToken, "allow-same-origin"))
120             flags &= ~SandboxOrigin;
121         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-forms"))
122             flags &= ~SandboxForms;
123         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-scripts")) {
124             flags &= ~SandboxScripts;
125             flags &= ~SandboxAutomaticFeatures;
126         } else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-top-navigation")) {
127             flags &= ~SandboxTopNavigation;
128             flags &= ~SandboxTopNavigationByUserActivation;
129         } else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-popups"))
130             flags &= ~SandboxPopups;
131         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-pointer-lock"))
132             flags &= ~SandboxPointerLock;
133         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-popups-to-escape-sandbox"))
134             flags &= ~SandboxPropagatesToAuxiliaryBrowsingContexts;
135         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-top-navigation-by-user-activation"))
136             flags &= ~SandboxTopNavigationByUserActivation;
137         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-modals"))
138             flags &= ~SandboxModals;
139         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-storage-access-by-user-activation"))
140             flags &= ~SandboxStorageAccessByUserActivation;
141         else {
142             if (numberOfTokenErrors)
143                 tokenErrors.appendLiteral(", '");
144             else
145                 tokenErrors.append('\'');
146             tokenErrors.append(sandboxToken);
147             tokenErrors.append('\'');
148             numberOfTokenErrors++;
149         }
150
151         start = end + 1;
152     }
153
154     if (numberOfTokenErrors) {
155         if (numberOfTokenErrors > 1)
156             tokenErrors.appendLiteral(" are invalid sandbox flags.");
157         else
158             tokenErrors.appendLiteral(" is an invalid sandbox flag.");
159         invalidTokensErrorMessage = tokenErrors.toString();
160     }
161
162     return flags;
163 }
164
165 }