tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ClientValidation.cpp (6530B)


      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/. */
      6 
      7 #include "ClientValidation.h"
      8 
      9 #include "mozilla/StaticPrefs_security.h"
     10 #include "mozilla/ipc/PBackgroundSharedTypes.h"
     11 #include "mozilla/net/MozURL.h"
     12 
     13 namespace mozilla::dom {
     14 
     15 using mozilla::ipc::ContentPrincipalInfo;
     16 using mozilla::ipc::PrincipalInfo;
     17 using mozilla::net::MozURL;
     18 
     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
     24  // origin/spec.
     25  switch (aPrincipalInfo.type()) {
     26    // Any system and null principal is acceptable.
     27    case PrincipalInfo::TSystemPrincipalInfo:
     28    case PrincipalInfo::TNullPrincipalInfo: {
     29      return true;
     30    }
     31 
     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();
     36 
     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);
     41 
     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);
     46 
     47      nsAutoCString originOrigin;
     48      originURL->Origin(originOrigin);
     49 
     50      nsAutoCString specOrigin;
     51      specURL->Origin(specOrigin);
     52 
     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
     57      // scheme.
     58      if (originURL->Scheme().Equals("moz-safe-about")) {
     59        return specOrigin == originOrigin ||
     60               specOrigin == Substring(originOrigin, 9 /*moz-safe-*/,
     61                                       specOrigin.Length());
     62      }
     63 
     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.
     70 
     71      return specOrigin == originOrigin;
     72    }
     73    default: {
     74      break;
     75    }
     76  }
     77 
     78  // Windows and workers should not have expanded URLs, etc.
     79  return false;
     80 }
     81 
     82 bool ClientIsValidCreationURL(const PrincipalInfo& aPrincipalInfo,
     83                              const nsACString& aURL) {
     84  RefPtr<MozURL> url;
     85  nsresult rv = MozURL::Init(getter_AddRefs(url), aURL);
     86  NS_ENSURE_SUCCESS(rv, false);
     87 
     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")) {
     93        return true;
     94      }
     95 
     96      const ContentPrincipalInfo& content =
     97          aPrincipalInfo.get_ContentPrincipalInfo();
     98 
     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);
    104 
    105      nsAutoCString origin;
    106      url->Origin(origin);
    107 
    108      nsAutoCString principalOrigin;
    109      principalURL->Origin(principalOrigin);
    110 
    111      // The vast majority of sites should simply result in the same principal
    112      // and URL origin.
    113      if (principalOrigin == origin) {
    114        return true;
    115      }
    116 
    117      nsDependentCSubstring scheme = url->Scheme();
    118 
    119      // Generally any origin can also open javascript: windows and workers.
    120      if (scheme.LowerCaseEqualsLiteral("javascript")) {
    121        return true;
    122      }
    123 
    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 ||
    130               origin ==
    131                   Substring(principalOrigin, 9 /*moz-safe-*/, origin.Length());
    132      }
    133 
    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.
    138      return false;
    139    }
    140    case PrincipalInfo::TSystemPrincipalInfo: {
    141      nsDependentCSubstring scheme = url->Scheme();
    142 
    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");
    152    }
    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
    158      // queries anyway.
    159      return true;
    160    }
    161    default: {
    162      break;
    163    }
    164  }
    165 
    166  // Clients (windows/workers) should never have an expanded principal type.
    167  return false;
    168 }
    169 
    170 }  // namespace mozilla::dom