1/*
2 * Copyright (C) 2012 Igalia S.L.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2,1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "config.h"
21#include "WebKitSecurityManager.h"
22
23#include "WebKitSecurityManagerPrivate.h"
24#include "WebKitWebContextPrivate.h"
25#include "WebProcessPool.h"
26#include <WebCore/SchemeRegistry.h>
27#include <wtf/glib/WTFGType.h>
28
29using namespace WebKit;
30
31/**
32 * SECTION: WebKitSecurityManager
33 * @Short_description: Controls security settings in a #WebKitWebContext
34 * @Title: WebKitSecurityManager
35 *
36 * The #WebKitSecurityManager defines security settings for URI
37 * schemes in a #WebKitWebContext. Get it from the context with
38 * webkit_web_context_get_security_manager(), and use it to register a
39 * URI scheme with a certain security level, or to check if it already
40 * has it.
41 *
42 */
43
44typedef enum {
45 SecurityPolicyLocal,
46 SecurityPolicyNoAccess,
47 SecurityPolicyDisplayIsolated,
48 SecurityPolicySecure,
49 SecurityPolicyCORSEnabled,
50 SecurityPolicyEmptyDocument
51} SecurityPolicy;
52
53struct _WebKitSecurityManagerPrivate {
54 WebKitWebContext* webContext;
55};
56
57WEBKIT_DEFINE_TYPE(WebKitSecurityManager, webkit_security_manager, G_TYPE_OBJECT)
58
59static void webkit_security_manager_class_init(WebKitSecurityManagerClass*)
60{
61}
62
63WebKitSecurityManager* webkitSecurityManagerCreate(WebKitWebContext* webContext)
64{
65 WebKitSecurityManager* manager = WEBKIT_SECURITY_MANAGER(g_object_new(WEBKIT_TYPE_SECURITY_MANAGER, NULL));
66 manager->priv->webContext = webContext;
67 return manager;
68}
69
70static void registerSecurityPolicyForURIScheme(WebKitSecurityManager* manager, const char* scheme, SecurityPolicy policy)
71{
72 String urlScheme = String::fromUTF8(scheme);
73 auto& processPool = webkitWebContextGetProcessPool(manager->priv->webContext);
74
75 // We keep the WebCore::SchemeRegistry of the UI process in sync with the
76 // web process one, so that we can return the SecurityPolicy for
77 // a given URI scheme synchronously without blocking.
78 switch (policy) {
79 case SecurityPolicyLocal:
80 WebCore::SchemeRegistry::registerURLSchemeAsLocal(urlScheme);
81 processPool.registerURLSchemeAsLocal(urlScheme);
82 break;
83 case SecurityPolicyNoAccess:
84 WebCore::SchemeRegistry::registerURLSchemeAsNoAccess(urlScheme);
85 processPool.registerURLSchemeAsNoAccess(urlScheme);
86 break;
87 case SecurityPolicyDisplayIsolated:
88 WebCore::SchemeRegistry::registerURLSchemeAsDisplayIsolated(urlScheme);
89 processPool.registerURLSchemeAsDisplayIsolated(urlScheme);
90 break;
91 case SecurityPolicySecure:
92 WebCore::SchemeRegistry::registerURLSchemeAsSecure(urlScheme);
93 processPool.registerURLSchemeAsSecure(urlScheme);
94 break;
95 case SecurityPolicyCORSEnabled:
96 WebCore::SchemeRegistry::registerURLSchemeAsCORSEnabled(urlScheme);
97 processPool.registerURLSchemeAsCORSEnabled(urlScheme);
98 break;
99 case SecurityPolicyEmptyDocument:
100 WebCore::SchemeRegistry::registerURLSchemeAsEmptyDocument(urlScheme);
101 processPool.registerURLSchemeAsEmptyDocument(urlScheme);
102 break;
103 }
104}
105
106static bool checkSecurityPolicyForURIScheme(const char* scheme, SecurityPolicy policy)
107{
108 String urlScheme = String::fromUTF8(scheme);
109
110 switch (policy) {
111 case SecurityPolicyLocal:
112 return WebCore::SchemeRegistry::shouldTreatURLSchemeAsLocal(urlScheme);
113 case SecurityPolicyNoAccess:
114 return WebCore::SchemeRegistry::shouldTreatURLSchemeAsNoAccess(urlScheme);
115 case SecurityPolicyDisplayIsolated:
116 return WebCore::SchemeRegistry::shouldTreatURLSchemeAsDisplayIsolated(urlScheme);
117 case SecurityPolicySecure:
118 return WebCore::SchemeRegistry::shouldTreatURLSchemeAsSecure(urlScheme);
119 case SecurityPolicyCORSEnabled:
120 return WebCore::SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(urlScheme);
121 case SecurityPolicyEmptyDocument:
122 return WebCore::SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(urlScheme);
123 }
124
125 return false;
126}
127
128/**
129 * webkit_security_manager_register_uri_scheme_as_local:
130 * @security_manager: a #WebKitSecurityManager
131 * @scheme: a URI scheme
132 *
133 * Register @scheme as a local scheme. This means that other non-local pages
134 * cannot link to or access URIs of this scheme.
135 */
136void webkit_security_manager_register_uri_scheme_as_local(WebKitSecurityManager* manager, const char* scheme)
137{
138 g_return_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager));
139 g_return_if_fail(scheme);
140
141 registerSecurityPolicyForURIScheme(manager, scheme, SecurityPolicyLocal);
142}
143
144/**
145 * webkit_security_manager_uri_scheme_is_local:
146 * @security_manager: a #WebKitSecurityManager
147 * @scheme: a URI scheme
148 *
149 * Whether @scheme is considered as a local scheme.
150 * See also webkit_security_manager_register_uri_scheme_as_local().
151 *
152 * Returns: %TRUE if @scheme is a local scheme or %FALSE otherwise.
153 */
154gboolean webkit_security_manager_uri_scheme_is_local(WebKitSecurityManager* manager, const char* scheme)
155{
156 g_return_val_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager), FALSE);
157 g_return_val_if_fail(scheme, FALSE);
158
159 return checkSecurityPolicyForURIScheme(scheme, SecurityPolicyLocal);
160}
161
162/**
163 * webkit_security_manager_register_uri_scheme_as_no_access:
164 * @security_manager: a #WebKitSecurityManager
165 * @scheme: a URI scheme
166 *
167 * Register @scheme as a no-access scheme. This means that pages loaded
168 * with this URI scheme cannot access pages loaded with any other URI scheme.
169 */
170void webkit_security_manager_register_uri_scheme_as_no_access(WebKitSecurityManager* manager, const char* scheme)
171{
172 g_return_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager));
173 g_return_if_fail(scheme);
174
175 registerSecurityPolicyForURIScheme(manager, scheme, SecurityPolicyNoAccess);
176}
177
178/**
179 * webkit_security_manager_uri_scheme_is_no_access:
180 * @security_manager: a #WebKitSecurityManager
181 * @scheme: a URI scheme
182 *
183 * Whether @scheme is considered as a no-access scheme.
184 * See also webkit_security_manager_register_uri_scheme_as_no_access().
185 *
186 * Returns: %TRUE if @scheme is a no-access scheme or %FALSE otherwise.
187 */
188gboolean webkit_security_manager_uri_scheme_is_no_access(WebKitSecurityManager* manager, const char* scheme)
189{
190 g_return_val_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager), FALSE);
191 g_return_val_if_fail(scheme, FALSE);
192
193 return checkSecurityPolicyForURIScheme(scheme, SecurityPolicyNoAccess);
194}
195
196/**
197 * webkit_security_manager_register_uri_scheme_as_display_isolated:
198 * @security_manager: a #WebKitSecurityManager
199 * @scheme: a URI scheme
200 *
201 * Register @scheme as a display isolated scheme. This means that pages cannot
202 * display these URIs unless they are from the same scheme.
203 */
204void webkit_security_manager_register_uri_scheme_as_display_isolated(WebKitSecurityManager* manager, const char* scheme)
205{
206 g_return_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager));
207 g_return_if_fail(scheme);
208
209 registerSecurityPolicyForURIScheme(manager, scheme, SecurityPolicyDisplayIsolated);
210}
211
212/**
213 * webkit_security_manager_uri_scheme_is_display_isolated:
214 * @security_manager: a #WebKitSecurityManager
215 * @scheme: a URI scheme
216 *
217 * Whether @scheme is considered as a display isolated scheme.
218 * See also webkit_security_manager_register_uri_scheme_as_display_isolated().
219 *
220 * Returns: %TRUE if @scheme is a display isolated scheme or %FALSE otherwise.
221 */
222gboolean webkit_security_manager_uri_scheme_is_display_isolated(WebKitSecurityManager* manager, const char* scheme)
223{
224 g_return_val_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager), FALSE);
225 g_return_val_if_fail(scheme, FALSE);
226
227 return checkSecurityPolicyForURIScheme(scheme, SecurityPolicyDisplayIsolated);
228}
229
230/**
231 * webkit_security_manager_register_uri_scheme_as_secure:
232 * @security_manager: a #WebKitSecurityManager
233 * @scheme: a URI scheme
234 *
235 * Register @scheme as a secure scheme. This means that mixed
236 * content warnings won't be generated for this scheme when
237 * included by an HTTPS page.
238 */
239void webkit_security_manager_register_uri_scheme_as_secure(WebKitSecurityManager* manager, const char* scheme)
240{
241 g_return_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager));
242 g_return_if_fail(scheme);
243
244 registerSecurityPolicyForURIScheme(manager, scheme, SecurityPolicySecure);
245}
246
247/**
248 * webkit_security_manager_uri_scheme_is_secure:
249 * @security_manager: a #WebKitSecurityManager
250 * @scheme: a URI scheme
251 *
252 * Whether @scheme is considered as a secure scheme.
253 * See also webkit_security_manager_register_uri_scheme_as_secure().
254 *
255 * Returns: %TRUE if @scheme is a secure scheme or %FALSE otherwise.
256 */
257gboolean webkit_security_manager_uri_scheme_is_secure(WebKitSecurityManager* manager, const char* scheme)
258{
259 g_return_val_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager), FALSE);
260 g_return_val_if_fail(scheme, FALSE);
261
262 return checkSecurityPolicyForURIScheme(scheme, SecurityPolicySecure);
263}
264
265/**
266 * webkit_security_manager_register_uri_scheme_as_cors_enabled:
267 * @security_manager: a #WebKitSecurityManager
268 * @scheme: a URI scheme
269 *
270 * Register @scheme as a CORS (Cross-origin resource sharing) enabled scheme.
271 * This means that CORS requests are allowed. See W3C CORS specification
272 * http://www.w3.org/TR/cors/.
273 */
274void webkit_security_manager_register_uri_scheme_as_cors_enabled(WebKitSecurityManager* manager, const char* scheme)
275{
276 g_return_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager));
277 g_return_if_fail(scheme);
278
279 registerSecurityPolicyForURIScheme(manager, scheme, SecurityPolicyCORSEnabled);
280}
281
282/**
283 * webkit_security_manager_uri_scheme_is_cors_enabled:
284 * @security_manager: a #WebKitSecurityManager
285 * @scheme: a URI scheme
286 *
287 * Whether @scheme is considered as a CORS enabled scheme.
288 * See also webkit_security_manager_register_uri_scheme_as_cors_enabled().
289 *
290 * Returns: %TRUE if @scheme is a CORS enabled scheme or %FALSE otherwise.
291 */
292gboolean webkit_security_manager_uri_scheme_is_cors_enabled(WebKitSecurityManager* manager, const char* scheme)
293{
294 g_return_val_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager), FALSE);
295 g_return_val_if_fail(scheme, FALSE);
296
297 return checkSecurityPolicyForURIScheme(scheme, SecurityPolicyCORSEnabled);
298}
299
300/**
301 * webkit_security_manager_register_uri_scheme_as_empty_document:
302 * @security_manager: a #WebKitSecurityManager
303 * @scheme: a URI scheme
304 *
305 * Register @scheme as an empty document scheme. This means that
306 * they are allowed to commit synchronously.
307 */
308void webkit_security_manager_register_uri_scheme_as_empty_document(WebKitSecurityManager* manager, const char* scheme)
309{
310 g_return_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager));
311 g_return_if_fail(scheme);
312
313 registerSecurityPolicyForURIScheme(manager, scheme, SecurityPolicyEmptyDocument);
314}
315
316/**
317 * webkit_security_manager_uri_scheme_is_empty_document:
318 * @security_manager: a #WebKitSecurityManager
319 * @scheme: a URI scheme
320 *
321 * Whether @scheme is considered as an empty document scheme.
322 * See also webkit_security_manager_register_uri_scheme_as_empty_document().
323 *
324 * Returns: %TRUE if @scheme is an empty document scheme or %FALSE otherwise.
325 */
326gboolean webkit_security_manager_uri_scheme_is_empty_document(WebKitSecurityManager* manager, const char* scheme)
327{
328 g_return_val_if_fail(WEBKIT_IS_SECURITY_MANAGER(manager), FALSE);
329 g_return_val_if_fail(scheme, FALSE);
330
331 return checkSecurityPolicyForURIScheme(scheme, SecurityPolicyEmptyDocument);
332}
333