tor-browser

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

PrincipalUtils.cpp (9306B)


      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/dom/quota/PrincipalUtils.h"
      8 
      9 #include "OriginParser.h"
     10 #include "mozilla/SystemPrincipal.h"
     11 #include "mozilla/dom/quota/CommonMetadata.h"
     12 #include "mozilla/dom/quota/Constants.h"
     13 #include "mozilla/dom/quota/QuotaCommon.h"
     14 #include "mozilla/dom/quota/QuotaManager.h"
     15 #include "mozilla/dom/quota/ResultExtensions.h"
     16 #include "mozilla/ipc/PBackgroundSharedTypes.h"
     17 #include "nsIScriptObjectPrincipal.h"
     18 #include "nsNetUtil.h"
     19 #include "nsPIDOMWindow.h"
     20 
     21 namespace mozilla::dom::quota {
     22 
     23 using namespace mozilla::ipc;
     24 
     25 bool IsPrincipalInfoValid(const PrincipalInfo& aPrincipalInfo) {
     26  switch (aPrincipalInfo.type()) {
     27    // A system principal is acceptable.
     28    case PrincipalInfo::TSystemPrincipalInfo: {
     29      return true;
     30    }
     31 
     32    // Validate content principals to ensure that the spec, originNoSuffix and
     33    // baseDomain are sane.
     34    case PrincipalInfo::TContentPrincipalInfo: {
     35      const ContentPrincipalInfo& info =
     36          aPrincipalInfo.get_ContentPrincipalInfo();
     37 
     38      // Verify the principal spec parses.
     39      nsCOMPtr<nsIURI> uri;
     40      QM_TRY(MOZ_TO_RESULT(NS_NewURI(getter_AddRefs(uri), info.spec())), false);
     41 
     42      nsCOMPtr<nsIPrincipal> principal =
     43          BasePrincipal::CreateContentPrincipal(uri, info.attrs());
     44      QM_TRY(MOZ_TO_RESULT(principal), false);
     45 
     46      // Verify the principal originNoSuffix matches spec.
     47      QM_TRY_INSPECT(const auto& originNoSuffix,
     48                     MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoCString, principal,
     49                                                       GetOriginNoSuffix),
     50                     false);
     51 
     52      if (NS_WARN_IF(originNoSuffix != info.originNoSuffix())) {
     53        QM_WARNING("originNoSuffix (%s) doesn't match passed one (%s)!",
     54                   originNoSuffix.get(), info.originNoSuffix().get());
     55        return false;
     56      }
     57 
     58      if (NS_WARN_IF(info.originNoSuffix().EqualsLiteral(kChromeOrigin))) {
     59        return false;
     60      }
     61 
     62      if (NS_WARN_IF(info.originNoSuffix().FindChar('^', 0) != -1)) {
     63        QM_WARNING("originNoSuffix (%s) contains the '^' character!",
     64                   info.originNoSuffix().get());
     65        return false;
     66      }
     67 
     68      // Verify the principal baseDomain exists.
     69      if (NS_WARN_IF(info.baseDomain().IsVoid())) {
     70        return false;
     71      }
     72 
     73      // Verify the principal baseDomain matches spec.
     74      QM_TRY_INSPECT(const auto& baseDomain,
     75                     MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(nsAutoCString, principal,
     76                                                       GetBaseDomain),
     77                     false);
     78 
     79      if (NS_WARN_IF(baseDomain != info.baseDomain())) {
     80        QM_WARNING("baseDomain (%s) doesn't match passed one (%s)!",
     81                   baseDomain.get(), info.baseDomain().get());
     82        return false;
     83      }
     84 
     85      return true;
     86    }
     87 
     88    default: {
     89      break;
     90    }
     91  }
     92 
     93  // Null and expanded principals are not acceptable.
     94  return false;
     95 }
     96 
     97 Result<PrincipalMetadata, nsresult> GetInfoFromValidatedPrincipalInfo(
     98    QuotaManager& aQuotaManager, const PrincipalInfo& aPrincipalInfo) {
     99  MOZ_ASSERT(IsPrincipalInfoValid(aPrincipalInfo));
    100 
    101  switch (aPrincipalInfo.type()) {
    102    case PrincipalInfo::TSystemPrincipalInfo: {
    103      return GetInfoForChrome();
    104    }
    105 
    106    case PrincipalInfo::TContentPrincipalInfo: {
    107      const ContentPrincipalInfo& info =
    108          aPrincipalInfo.get_ContentPrincipalInfo();
    109 
    110      nsCString suffix;
    111      info.attrs().CreateSuffix(suffix);
    112 
    113      nsCString origin = info.originNoSuffix() + suffix;
    114 
    115      if (IsUUIDOrigin(origin)) {
    116        QM_TRY_INSPECT(const auto& originalOrigin,
    117                       aQuotaManager.GetOriginFromStorageOrigin(origin));
    118 
    119        nsCOMPtr<nsIPrincipal> principal =
    120            BasePrincipal::CreateContentPrincipal(originalOrigin);
    121        QM_TRY(MOZ_TO_RESULT(principal));
    122 
    123        PrincipalInfo principalInfo;
    124        QM_TRY(
    125            MOZ_TO_RESULT(PrincipalToPrincipalInfo(principal, &principalInfo)));
    126 
    127        return GetInfoFromValidatedPrincipalInfo(aQuotaManager, principalInfo);
    128      }
    129 
    130      PrincipalMetadata principalMetadata;
    131 
    132      principalMetadata.mSuffix = suffix;
    133 
    134      principalMetadata.mGroup = info.baseDomain() + suffix;
    135 
    136      principalMetadata.mOrigin = origin;
    137 
    138      if (info.attrs().IsPrivateBrowsing()) {
    139        QM_TRY_UNWRAP(principalMetadata.mStorageOrigin,
    140                      aQuotaManager.EnsureStorageOriginFromOrigin(origin));
    141      } else {
    142        principalMetadata.mStorageOrigin = origin;
    143      }
    144 
    145      principalMetadata.mIsPrivate = info.attrs().IsPrivateBrowsing();
    146 
    147      return principalMetadata;
    148    }
    149 
    150    default: {
    151      MOZ_ASSERT_UNREACHABLE("Should never get here!");
    152      return Err(NS_ERROR_UNEXPECTED);
    153    }
    154  }
    155 }
    156 
    157 nsAutoCString GetGroupFromValidatedPrincipalInfo(
    158    const PrincipalInfo& aPrincipalInfo) {
    159  MOZ_ASSERT(IsPrincipalInfoValid(aPrincipalInfo));
    160 
    161  switch (aPrincipalInfo.type()) {
    162    case PrincipalInfo::TSystemPrincipalInfo: {
    163      return nsAutoCString{GetGroupForChrome()};
    164    }
    165 
    166    case PrincipalInfo::TContentPrincipalInfo: {
    167      const ContentPrincipalInfo& info =
    168          aPrincipalInfo.get_ContentPrincipalInfo();
    169 
    170      nsAutoCString suffix;
    171 
    172      info.attrs().CreateSuffix(suffix);
    173 
    174      return info.baseDomain() + suffix;
    175    }
    176 
    177    default: {
    178      MOZ_CRASH("Should never get here!");
    179    }
    180  }
    181 }
    182 
    183 nsAutoCString GetOriginFromValidatedPrincipalInfo(
    184    const PrincipalInfo& aPrincipalInfo) {
    185  MOZ_ASSERT(IsPrincipalInfoValid(aPrincipalInfo));
    186 
    187  switch (aPrincipalInfo.type()) {
    188    case PrincipalInfo::TSystemPrincipalInfo: {
    189      return nsAutoCString{GetOriginForChrome()};
    190    }
    191 
    192    case PrincipalInfo::TContentPrincipalInfo: {
    193      const ContentPrincipalInfo& info =
    194          aPrincipalInfo.get_ContentPrincipalInfo();
    195 
    196      nsAutoCString suffix;
    197 
    198      info.attrs().CreateSuffix(suffix);
    199 
    200      return info.originNoSuffix() + suffix;
    201    }
    202 
    203    default: {
    204      MOZ_CRASH("Should never get here!");
    205    }
    206  }
    207 }
    208 
    209 Result<PrincipalMetadata, nsresult> GetInfoFromPrincipal(
    210    nsIPrincipal* aPrincipal) {
    211  MOZ_ASSERT(aPrincipal);
    212 
    213  if (aPrincipal->IsSystemPrincipal()) {
    214    return GetInfoForChrome();
    215  }
    216 
    217  if (aPrincipal->GetIsNullPrincipal()) {
    218    NS_WARNING("IndexedDB not supported from this principal!");
    219    return Err(NS_ERROR_FAILURE);
    220  }
    221 
    222  PrincipalMetadata principalMetadata;
    223 
    224  QM_TRY(MOZ_TO_RESULT(aPrincipal->GetOrigin(principalMetadata.mOrigin)));
    225 
    226  if (principalMetadata.mOrigin.EqualsLiteral(kChromeOrigin)) {
    227    NS_WARNING("Non-chrome principal can't use chrome origin!");
    228    return Err(NS_ERROR_FAILURE);
    229  }
    230 
    231  aPrincipal->OriginAttributesRef().CreateSuffix(principalMetadata.mSuffix);
    232 
    233  nsAutoCString baseDomain;
    234  QM_TRY(MOZ_TO_RESULT(aPrincipal->GetBaseDomain(baseDomain)));
    235 
    236  MOZ_ASSERT(!baseDomain.IsEmpty());
    237 
    238  principalMetadata.mGroup = baseDomain + principalMetadata.mSuffix;
    239 
    240  principalMetadata.mStorageOrigin = principalMetadata.mOrigin;
    241 
    242  principalMetadata.mIsPrivate = aPrincipal->GetIsInPrivateBrowsing();
    243 
    244  return principalMetadata;
    245 }
    246 
    247 Result<PrincipalMetadata, nsresult> GetInfoFromWindow(
    248    nsPIDOMWindowOuter* aWindow) {
    249  MOZ_ASSERT(NS_IsMainThread());
    250  MOZ_ASSERT(aWindow);
    251 
    252  nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow);
    253  QM_TRY(OkIf(sop), Err(NS_ERROR_FAILURE));
    254 
    255  nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
    256  QM_TRY(OkIf(principal), Err(NS_ERROR_FAILURE));
    257 
    258  return GetInfoFromPrincipal(principal);
    259 }
    260 
    261 Result<nsAutoCString, nsresult> GetOriginFromPrincipal(
    262    nsIPrincipal* aPrincipal) {
    263  MOZ_ASSERT(NS_IsMainThread());
    264  MOZ_ASSERT(aPrincipal);
    265 
    266  if (aPrincipal->IsSystemPrincipal()) {
    267    return nsAutoCString{GetOriginForChrome()};
    268  }
    269 
    270  if (aPrincipal->GetIsNullPrincipal()) {
    271    NS_WARNING("IndexedDB not supported from this principal!");
    272    return Err(NS_ERROR_FAILURE);
    273  }
    274 
    275  QM_TRY_UNWRAP(const auto origin, MOZ_TO_RESULT_INVOKE_MEMBER_TYPED(
    276                                       nsAutoCString, aPrincipal, GetOrigin));
    277 
    278  if (origin.EqualsLiteral(kChromeOrigin)) {
    279    NS_WARNING("Non-chrome principal can't use chrome origin!");
    280    return Err(NS_ERROR_FAILURE);
    281  }
    282 
    283  return origin;
    284 }
    285 
    286 Result<nsAutoCString, nsresult> GetOriginFromWindow(
    287    nsPIDOMWindowOuter* aWindow) {
    288  MOZ_ASSERT(NS_IsMainThread());
    289  MOZ_ASSERT(aWindow);
    290 
    291  nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow);
    292  QM_TRY(OkIf(sop), Err(NS_ERROR_FAILURE));
    293 
    294  nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
    295  QM_TRY(OkIf(principal), Err(NS_ERROR_FAILURE));
    296 
    297  QM_TRY_RETURN(GetOriginFromPrincipal(principal));
    298 }
    299 
    300 PrincipalMetadata GetInfoForChrome() {
    301  return {{},
    302          GetGroupForChrome(),
    303          GetOriginForChrome(),
    304          GetOriginForChrome(),
    305          false};
    306 }
    307 
    308 nsLiteralCString GetGroupForChrome() { return nsLiteralCString{kChromeOrigin}; }
    309 
    310 nsLiteralCString GetOriginForChrome() {
    311  return nsLiteralCString{kChromeOrigin};
    312 }
    313 
    314 }  // namespace mozilla::dom::quota