/* 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/dom/ProcessIsolation.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, const nsACString& aRemoteType) { auto result = mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalInfo); if (NS_WARN_IF(result.isErr())) { return false; } nsCOMPtr principal = result.unwrap(); // FIXME: Remove the system allowance once for non-inference processes once we // can load documents with the system principal into content. if (NS_WARN_IF(!ValidatePrincipalCouldPotentiallyBeLoadedBy( principal, aRemoteType, {ValidatePrincipalOptions::AllowSystem}))) { return false; } // Windows and workers should not have expanded principals, etc. return principal->IsSystemPrincipal() || principal->GetIsNullPrincipal() || principal->GetIsContentPrincipal(); } bool ClientIsValidCreationURL(const PrincipalInfo& aPrincipalInfo, const nsACString& aURL) { RefPtr 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 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; } // 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