tor-browser

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

DomainPolicy.cpp (6142B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=4 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 "DomainPolicy.h"
      8 #include "mozilla/dom/ContentParent.h"
      9 #include "mozilla/ipc/URIUtils.h"
     10 #include "nsIURIMutator.h"
     11 #include "nsScriptSecurityManager.h"
     12 
     13 namespace mozilla {
     14 
     15 using namespace ipc;
     16 using namespace dom;
     17 
     18 NS_IMPL_ISUPPORTS(DomainPolicy, nsIDomainPolicy)
     19 
     20 static nsresult BroadcastDomainSetChange(DomainSetType aSetType,
     21                                         DomainSetChangeType aChangeType,
     22                                         nsIURI* aDomain = nullptr) {
     23  MOZ_ASSERT(XRE_IsParentProcess(),
     24             "DomainPolicy should only be exposed to the chrome process.");
     25 
     26  nsTArray<ContentParent*> parents;
     27  ContentParent::GetAll(parents);
     28  if (!parents.Length()) {
     29    return NS_OK;
     30  }
     31 
     32  for (uint32_t i = 0; i < parents.Length(); i++) {
     33    (void)parents[i]->SendDomainSetChanged(aSetType, aChangeType, aDomain);
     34  }
     35  return NS_OK;
     36 }
     37 
     38 DomainPolicy::DomainPolicy()
     39    : mBlocklist(new DomainSet(BLOCKLIST)),
     40      mSuperBlocklist(new DomainSet(SUPER_BLOCKLIST)),
     41      mAllowlist(new DomainSet(ALLOWLIST)),
     42      mSuperAllowlist(new DomainSet(SUPER_ALLOWLIST)) {
     43  if (XRE_IsParentProcess()) {
     44    BroadcastDomainSetChange(NO_TYPE, ACTIVATE_POLICY);
     45  }
     46 }
     47 
     48 DomainPolicy::~DomainPolicy() {
     49  // The SSM holds a strong ref to the DomainPolicy until Deactivate() is
     50  // invoked, so we should never hit the destructor until that happens.
     51  MOZ_ASSERT(!mBlocklist && !mSuperBlocklist && !mAllowlist &&
     52             !mSuperAllowlist);
     53 }
     54 
     55 NS_IMETHODIMP
     56 DomainPolicy::GetBlocklist(nsIDomainSet** aSet) {
     57  nsCOMPtr<nsIDomainSet> set = mBlocklist.get();
     58  set.forget(aSet);
     59  return NS_OK;
     60 }
     61 
     62 NS_IMETHODIMP
     63 DomainPolicy::GetSuperBlocklist(nsIDomainSet** aSet) {
     64  nsCOMPtr<nsIDomainSet> set = mSuperBlocklist.get();
     65  set.forget(aSet);
     66  return NS_OK;
     67 }
     68 
     69 NS_IMETHODIMP
     70 DomainPolicy::GetAllowlist(nsIDomainSet** aSet) {
     71  nsCOMPtr<nsIDomainSet> set = mAllowlist.get();
     72  set.forget(aSet);
     73  return NS_OK;
     74 }
     75 
     76 NS_IMETHODIMP
     77 DomainPolicy::GetSuperAllowlist(nsIDomainSet** aSet) {
     78  nsCOMPtr<nsIDomainSet> set = mSuperAllowlist.get();
     79  set.forget(aSet);
     80  return NS_OK;
     81 }
     82 
     83 NS_IMETHODIMP
     84 DomainPolicy::Deactivate() {
     85  // Clear the hashtables first to free up memory, since script might
     86  // hold the doomed sets alive indefinitely.
     87  mBlocklist->Clear();
     88  mSuperBlocklist->Clear();
     89  mAllowlist->Clear();
     90  mSuperAllowlist->Clear();
     91 
     92  // Null them out.
     93  mBlocklist = nullptr;
     94  mSuperBlocklist = nullptr;
     95  mAllowlist = nullptr;
     96  mSuperAllowlist = nullptr;
     97 
     98  // Inform the SSM.
     99  nsScriptSecurityManager* ssm =
    100      nsScriptSecurityManager::GetScriptSecurityManager();
    101  if (ssm) {
    102    ssm->DeactivateDomainPolicy();
    103  }
    104  if (XRE_IsParentProcess()) {
    105    BroadcastDomainSetChange(NO_TYPE, DEACTIVATE_POLICY);
    106  }
    107  return NS_OK;
    108 }
    109 
    110 void DomainPolicy::CloneDomainPolicy(DomainPolicyClone* aClone) {
    111  aClone->active() = true;
    112  mBlocklist->CloneSet(&aClone->blocklist());
    113  mSuperBlocklist->CloneSet(&aClone->superBlocklist());
    114  mAllowlist->CloneSet(&aClone->allowlist());
    115  mSuperAllowlist->CloneSet(&aClone->superAllowlist());
    116 }
    117 
    118 static void CopyURIs(const nsTArray<RefPtr<nsIURI>>& aDomains,
    119                     nsIDomainSet* aSet) {
    120  for (uint32_t i = 0; i < aDomains.Length(); i++) {
    121    if (NS_WARN_IF(!aDomains[i])) {
    122      continue;
    123    }
    124    aSet->Add(aDomains[i]);
    125  }
    126 }
    127 
    128 void DomainPolicy::ApplyClone(const DomainPolicyClone* aClone) {
    129  CopyURIs(aClone->blocklist(), mBlocklist);
    130  CopyURIs(aClone->allowlist(), mAllowlist);
    131  CopyURIs(aClone->superBlocklist(), mSuperBlocklist);
    132  CopyURIs(aClone->superAllowlist(), mSuperAllowlist);
    133 }
    134 
    135 static already_AddRefed<nsIURI> GetCanonicalClone(nsIURI* aURI) {
    136  nsCOMPtr<nsIURI> clone;
    137  nsresult rv =
    138      NS_MutateURI(aURI).SetUserPass(""_ns).SetPathQueryRef(""_ns).Finalize(
    139          clone);
    140  NS_ENSURE_SUCCESS(rv, nullptr);
    141  return clone.forget();
    142 }
    143 
    144 NS_IMPL_ISUPPORTS(DomainSet, nsIDomainSet)
    145 
    146 NS_IMETHODIMP
    147 DomainSet::Add(nsIURI* aDomain) {
    148  nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
    149  NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
    150  mHashTable.Insert(clone);
    151  if (XRE_IsParentProcess()) {
    152    return BroadcastDomainSetChange(mType, ADD_DOMAIN, aDomain);
    153  }
    154 
    155  return NS_OK;
    156 }
    157 
    158 NS_IMETHODIMP
    159 DomainSet::Remove(nsIURI* aDomain) {
    160  nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
    161  NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
    162  mHashTable.Remove(clone);
    163  if (XRE_IsParentProcess()) {
    164    return BroadcastDomainSetChange(mType, REMOVE_DOMAIN, aDomain);
    165  }
    166 
    167  return NS_OK;
    168 }
    169 
    170 NS_IMETHODIMP
    171 DomainSet::Clear() {
    172  mHashTable.Clear();
    173  if (XRE_IsParentProcess()) {
    174    return BroadcastDomainSetChange(mType, CLEAR_DOMAINS);
    175  }
    176 
    177  return NS_OK;
    178 }
    179 
    180 NS_IMETHODIMP
    181 DomainSet::Contains(nsIURI* aDomain, bool* aContains) {
    182  *aContains = false;
    183  nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
    184  NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
    185  *aContains = mHashTable.Contains(clone);
    186  return NS_OK;
    187 }
    188 
    189 NS_IMETHODIMP
    190 DomainSet::ContainsSuperDomain(nsIURI* aDomain, bool* aContains) {
    191  *aContains = false;
    192  nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
    193  NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
    194  nsAutoCString domain;
    195  nsresult rv = clone->GetHost(domain);
    196  NS_ENSURE_SUCCESS(rv, rv);
    197  while (true) {
    198    // Check the current domain.
    199    if (mHashTable.Contains(clone)) {
    200      *aContains = true;
    201      return NS_OK;
    202    }
    203 
    204    // Chop off everything before the first dot, or break if there are no
    205    // dots left.
    206    int32_t index = domain.Find(".");
    207    if (index == kNotFound) break;
    208    domain.Assign(Substring(domain, index + 1));
    209    rv = NS_MutateURI(clone).SetHost(domain).Finalize(clone);
    210    NS_ENSURE_SUCCESS(rv, rv);
    211  }
    212 
    213  // No match.
    214  return NS_OK;
    215 }
    216 
    217 void DomainSet::CloneSet(nsTArray<RefPtr<nsIURI>>* aDomains) {
    218  AppendToArray(*aDomains, mHashTable);
    219 }
    220 
    221 } /* namespace mozilla */