Use "= default" to denote default constructor or destructor
[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() = default;
39
40 SecurityContext::~SecurityContext() = default;
41
42 void SecurityContext::setSecurityOriginPolicy(RefPtr<SecurityOriginPolicy>&& securityOriginPolicy)
43 {
44     m_securityOriginPolicy = WTFMove(securityOriginPolicy);
45     m_haveInitializedSecurityOrigin = true;
46 }
47
48 SecurityOrigin* SecurityContext::securityOrigin() const
49 {
50     if (!m_securityOriginPolicy)
51         return nullptr;
52
53     return &m_securityOriginPolicy->origin();
54 }
55
56 void SecurityContext::setContentSecurityPolicy(std::unique_ptr<ContentSecurityPolicy> contentSecurityPolicy)
57 {
58     m_contentSecurityPolicy = WTFMove(contentSecurityPolicy);
59 }
60
61 bool SecurityContext::isSecureTransitionTo(const URL& url) const
62 {
63     // If we haven't initialized our security origin by now, this is probably
64     // a new window created via the API (i.e., that lacks an origin and lacks
65     // a place to inherit the origin from).
66     if (!haveInitializedSecurityOrigin())
67         return true;
68
69     return securityOriginPolicy()->origin().canAccess(SecurityOrigin::create(url).get());
70 }
71
72 void SecurityContext::enforceSandboxFlags(SandboxFlags mask)
73 {
74     m_sandboxFlags |= mask;
75
76     // The SandboxOrigin is stored redundantly in the security origin.
77     if (isSandboxed(SandboxOrigin) && securityOriginPolicy() && !securityOriginPolicy()->origin().isUnique())
78         setSecurityOriginPolicy(SecurityOriginPolicy::create(SecurityOrigin::createUnique()));
79 }
80
81 bool SecurityContext::isSupportedSandboxPolicy(StringView policy)
82 {
83     static const char* const supportedPolicies[] = {
84         "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"
85     };
86
87     for (auto* supportedPolicy : supportedPolicies) {
88         if (equalIgnoringASCIICase(policy, supportedPolicy))
89             return true;
90     }
91     return false;
92 }
93
94 // Keep SecurityContext::isSupportedSandboxPolicy() in sync when updating this function.
95 SandboxFlags SecurityContext::parseSandboxPolicy(const String& policy, String& invalidTokensErrorMessage)
96 {
97     // http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
98     // Parse the unordered set of unique space-separated tokens.
99     SandboxFlags flags = SandboxAll;
100     unsigned length = policy.length();
101     unsigned start = 0;
102     unsigned numberOfTokenErrors = 0;
103     StringBuilder tokenErrors;
104     while (true) {
105         while (start < length && isHTMLSpace(policy[start]))
106             ++start;
107         if (start >= length)
108             break;
109         unsigned end = start + 1;
110         while (end < length && !isHTMLSpace(policy[end]))
111             ++end;
112
113         // Turn off the corresponding sandbox flag if it's set as "allowed".
114         String sandboxToken = policy.substring(start, end - start);
115         if (equalLettersIgnoringASCIICase(sandboxToken, "allow-same-origin"))
116             flags &= ~SandboxOrigin;
117         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-forms"))
118             flags &= ~SandboxForms;
119         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-scripts")) {
120             flags &= ~SandboxScripts;
121             flags &= ~SandboxAutomaticFeatures;
122         } else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-top-navigation")) {
123             flags &= ~SandboxTopNavigation;
124             flags &= ~SandboxTopNavigationByUserActivation;
125         } else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-popups"))
126             flags &= ~SandboxPopups;
127         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-pointer-lock"))
128             flags &= ~SandboxPointerLock;
129         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-popups-to-escape-sandbox"))
130             flags &= ~SandboxPropagatesToAuxiliaryBrowsingContexts;
131         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-top-navigation-by-user-activation"))
132             flags &= ~SandboxTopNavigationByUserActivation;
133         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-modals"))
134             flags &= ~SandboxModals;
135         else if (equalLettersIgnoringASCIICase(sandboxToken, "allow-storage-access-by-user-activation"))
136             flags &= ~SandboxStorageAccessByUserActivation;
137         else {
138             if (numberOfTokenErrors)
139                 tokenErrors.appendLiteral(", '");
140             else
141                 tokenErrors.append('\'');
142             tokenErrors.append(sandboxToken);
143             tokenErrors.append('\'');
144             numberOfTokenErrors++;
145         }
146
147         start = end + 1;
148     }
149
150     if (numberOfTokenErrors) {
151         if (numberOfTokenErrors > 1)
152             tokenErrors.appendLiteral(" are invalid sandbox flags.");
153         else
154             tokenErrors.appendLiteral(" is an invalid sandbox flag.");
155         invalidTokensErrorMessage = tokenErrors.toString();
156     }
157
158     return flags;
159 }
160
161 }