summaryrefslogtreecommitdiffstats
path: root/dom/clients/manager/ClientValidation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/clients/manager/ClientValidation.cpp')
-rw-r--r--dom/clients/manager/ClientValidation.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/dom/clients/manager/ClientValidation.cpp b/dom/clients/manager/ClientValidation.cpp
new file mode 100644
index 0000000000..61e9338e12
--- /dev/null
+++ b/dom/clients/manager/ClientValidation.cpp
@@ -0,0 +1,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/ipc/PBackgroundSharedTypes.h"
+#include "mozilla/StaticPrefs_security.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