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