1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ClientValidation.h"
9 #include "mozilla/ipc/PBackgroundSharedTypes.h"
10 #include "mozilla/StaticPrefs_security.h"
11 #include "mozilla/net/MozURL.h"
13 namespace mozilla::dom
{
15 using mozilla::ipc::ContentPrincipalInfo
;
16 using mozilla::ipc::PrincipalInfo
;
17 using mozilla::net::MozURL
;
19 bool ClientIsValidPrincipalInfo(const PrincipalInfo
& aPrincipalInfo
) {
20 // Ideally we would verify that the source process has permission to
21 // create a window or worker with the given principal, but we don't
22 // currently have any such restriction in place. Instead, at least
23 // verify the PrincipalInfo is an expected type and has a parsable
25 switch (aPrincipalInfo
.type()) {
26 // Any system and null principal is acceptable.
27 case PrincipalInfo::TSystemPrincipalInfo
:
28 case PrincipalInfo::TNullPrincipalInfo
: {
32 // Validate content principals to ensure that the origin and spec are sane.
33 case PrincipalInfo::TContentPrincipalInfo
: {
34 const ContentPrincipalInfo
& content
=
35 aPrincipalInfo
.get_ContentPrincipalInfo();
37 // Verify the principal spec parses.
38 RefPtr
<MozURL
> specURL
;
39 nsresult rv
= MozURL::Init(getter_AddRefs(specURL
), content
.spec());
40 NS_ENSURE_SUCCESS(rv
, false);
42 // Verify the principal originNoSuffix parses.
43 RefPtr
<MozURL
> originURL
;
44 rv
= MozURL::Init(getter_AddRefs(originURL
), content
.originNoSuffix());
45 NS_ENSURE_SUCCESS(rv
, false);
47 nsAutoCString originOrigin
;
48 originURL
->Origin(originOrigin
);
50 nsAutoCString specOrigin
;
51 specURL
->Origin(specOrigin
);
53 // Linkable about URIs end up with a nested inner scheme of moz-safe-about
54 // which will have been captured in the originNoSuffix but the spec and
55 // its resulting specOrigin will not have this transformed scheme, so
56 // ignore the "moz-safe-" prefix when the originURL has that transformed
58 if (originURL
->Scheme().Equals("moz-safe-about")) {
59 return specOrigin
== originOrigin
||
60 specOrigin
== Substring(originOrigin
, 9 /*moz-safe-*/,
64 // For now require Clients to have a principal where both its
65 // originNoSuffix and spec have the same origin. This will
66 // exclude a variety of unusual combinations within the browser
67 // but its adequate for the features need to support right now.
68 // If necessary we could expand this function to handle more
69 // cases in the future.
71 return specOrigin
== originOrigin
;
78 // Windows and workers should not have expanded URLs, etc.
82 bool ClientIsValidCreationURL(const PrincipalInfo
& aPrincipalInfo
,
83 const nsACString
& aURL
) {
85 nsresult rv
= MozURL::Init(getter_AddRefs(url
), aURL
);
86 NS_ENSURE_SUCCESS(rv
, false);
88 switch (aPrincipalInfo
.type()) {
89 case PrincipalInfo::TContentPrincipalInfo
: {
90 // Any origin can create an about:blank or about:srcdoc Client.
91 if (aURL
.LowerCaseEqualsLiteral("about:blank") ||
92 aURL
.LowerCaseEqualsLiteral("about:srcdoc")) {
96 const ContentPrincipalInfo
& content
=
97 aPrincipalInfo
.get_ContentPrincipalInfo();
99 // Parse the principal origin URL as well. This ensures any MozURL
100 // parser issues effect both URLs equally.
101 RefPtr
<MozURL
> principalURL
;
102 rv
= MozURL::Init(getter_AddRefs(principalURL
), content
.originNoSuffix());
103 NS_ENSURE_SUCCESS(rv
, false);
105 nsAutoCString origin
;
108 nsAutoCString principalOrigin
;
109 principalURL
->Origin(principalOrigin
);
111 // The vast majority of sites should simply result in the same principal
113 if (principalOrigin
== origin
) {
117 nsDependentCSubstring scheme
= url
->Scheme();
119 // Generally any origin can also open javascript: windows and workers.
120 if (scheme
.LowerCaseEqualsLiteral("javascript")) {
124 // Linkable about URIs end up with a nested inner scheme of moz-safe-about
125 // but the url and its resulting origin will not have this transformed
126 // scheme, so ignore the "moz-safe-" prefix when the principal has that
127 // transformed scheme.
128 if (principalURL
->Scheme().Equals("moz-safe-about")) {
129 return origin
== principalOrigin
||
131 Substring(principalOrigin
, 9 /*moz-safe-*/, origin
.Length());
134 // Otherwise don't support this URL type in the clients sub-system for
135 // now. This will exclude a variety of internal browser clients, but
136 // currently we don't need to support those. This function can be
137 // expanded to handle more cases as necessary.
140 case PrincipalInfo::TSystemPrincipalInfo
: {
141 nsDependentCSubstring scheme
= url
->Scheme();
143 // While many types of documents can be created with a system principal,
144 // there are only a few that can reasonably become windows. We attempt
145 // to validate the list of known cases here with a simple scheme check.
146 return scheme
.LowerCaseEqualsLiteral("about") ||
147 scheme
.LowerCaseEqualsLiteral("chrome") ||
148 scheme
.LowerCaseEqualsLiteral("resource") ||
149 scheme
.LowerCaseEqualsLiteral("blob") ||
150 scheme
.LowerCaseEqualsLiteral("javascript") ||
151 scheme
.LowerCaseEqualsLiteral("view-source");
153 case PrincipalInfo::TNullPrincipalInfo
: {
154 // A wide variety of clients can have a null principal. For example,
155 // sandboxed iframes can have a normal content URL. For now allow
156 // any parsable URL for null principals. This is relatively safe since
157 // null principals have unique origins and won't most ClientManagerService
166 // Clients (windows/workers) should never have an expanded principal type.
170 } // namespace mozilla::dom