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