Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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