tor-browser

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

FeaturePolicyParser.cpp (4623B)


      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 "FeaturePolicyParser.h"
      8 
      9 #include "mozilla/BasePrincipal.h"
     10 #include "mozilla/dom/Feature.h"
     11 #include "mozilla/dom/FeaturePolicyUtils.h"
     12 #include "mozilla/dom/PolicyTokenizer.h"
     13 #include "nsIScriptError.h"
     14 #include "nsIURI.h"
     15 #include "nsNetUtil.h"
     16 
     17 namespace mozilla::dom {
     18 
     19 namespace {
     20 
     21 void ReportToConsoleUnsupportedFeature(Document* aDocument,
     22                                       const nsString& aFeatureName) {
     23  if (!aDocument) {
     24    return;
     25  }
     26 
     27  AutoTArray<nsString, 1> params = {aFeatureName};
     28 
     29  nsContentUtils::ReportToConsole(
     30      nsIScriptError::warningFlag, "Feature Policy"_ns, aDocument,
     31      nsContentUtils::eSECURITY_PROPERTIES,
     32      "FeaturePolicyUnsupportedFeatureName", params);
     33 }
     34 
     35 void ReportToConsoleInvalidEmptyAllowValue(Document* aDocument,
     36                                           const nsString& aFeatureName) {
     37  if (!aDocument) {
     38    return;
     39  }
     40 
     41  AutoTArray<nsString, 1> params = {aFeatureName};
     42 
     43  nsContentUtils::ReportToConsole(
     44      nsIScriptError::warningFlag, "Feature Policy"_ns, aDocument,
     45      nsContentUtils::eSECURITY_PROPERTIES,
     46      "FeaturePolicyInvalidEmptyAllowValue", params);
     47 }
     48 
     49 void ReportToConsoleInvalidAllowValue(Document* aDocument,
     50                                      const nsString& aValue) {
     51  if (!aDocument) {
     52    return;
     53  }
     54 
     55  AutoTArray<nsString, 1> params = {aValue};
     56 
     57  nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
     58                                  "Feature Policy"_ns, aDocument,
     59                                  nsContentUtils::eSECURITY_PROPERTIES,
     60                                  "FeaturePolicyInvalidAllowValue", params);
     61 }
     62 
     63 }  // namespace
     64 
     65 /* static */
     66 bool FeaturePolicyParser::ParseString(const nsAString& aPolicy,
     67                                      Document* aDocument,
     68                                      nsIPrincipal* aSelfOrigin,
     69                                      nsIPrincipal* aSrcOrigin,
     70                                      nsTArray<Feature>& aParsedFeatures) {
     71  MOZ_ASSERT(aSelfOrigin);
     72 
     73  nsTArray<CopyableTArray<nsString>> tokens;
     74  PolicyTokenizer::tokenizePolicy(aPolicy, tokens);
     75 
     76  nsTArray<Feature> parsedFeatures;
     77 
     78  for (const nsTArray<nsString>& featureTokens : tokens) {
     79    if (featureTokens.IsEmpty()) {
     80      continue;
     81    }
     82 
     83    if (!FeaturePolicyUtils::IsSupportedFeature(featureTokens[0])) {
     84      ReportToConsoleUnsupportedFeature(aDocument, featureTokens[0]);
     85      continue;
     86    }
     87 
     88    Feature feature(featureTokens[0]);
     89 
     90    if (featureTokens.Length() == 1) {
     91      if (aSrcOrigin) {
     92        feature.AppendToAllowList(aSrcOrigin);
     93      } else {
     94        ReportToConsoleInvalidEmptyAllowValue(aDocument, featureTokens[0]);
     95        continue;
     96      }
     97    } else {
     98      // we gotta start at 1 here
     99      for (uint32_t i = 1; i < featureTokens.Length(); ++i) {
    100        const nsString& curVal = featureTokens[i];
    101        if (curVal.LowerCaseEqualsASCII("'none'")) {
    102          feature.SetAllowsNone();
    103          break;
    104        }
    105 
    106        if (curVal.EqualsLiteral("*")) {
    107          feature.SetAllowsAll();
    108          break;
    109        }
    110 
    111        if (curVal.LowerCaseEqualsASCII("'self'")) {
    112          feature.AppendToAllowList(aSelfOrigin);
    113          continue;
    114        }
    115 
    116        if (aSrcOrigin && curVal.LowerCaseEqualsASCII("'src'")) {
    117          feature.AppendToAllowList(aSrcOrigin);
    118          continue;
    119        }
    120 
    121        nsCOMPtr<nsIURI> uri;
    122        nsresult rv = NS_NewURI(getter_AddRefs(uri), curVal);
    123        if (NS_FAILED(rv)) {
    124          ReportToConsoleInvalidAllowValue(aDocument, curVal);
    125          continue;
    126        }
    127 
    128        nsCOMPtr<nsIPrincipal> origin = BasePrincipal::CreateContentPrincipal(
    129            uri, BasePrincipal::Cast(aSelfOrigin)->OriginAttributesRef());
    130        if (NS_WARN_IF(!origin)) {
    131          ReportToConsoleInvalidAllowValue(aDocument, curVal);
    132          continue;
    133        }
    134 
    135        feature.AppendToAllowList(origin);
    136      }
    137    }
    138 
    139    // No duplicate!
    140    bool found = false;
    141    for (const Feature& parsedFeature : parsedFeatures) {
    142      if (parsedFeature.Name() == feature.Name()) {
    143        found = true;
    144        break;
    145      }
    146    }
    147 
    148    if (!found) {
    149      parsedFeatures.AppendElement(feature);
    150    }
    151  }
    152 
    153  aParsedFeatures = std::move(parsedFeatures);
    154  return true;
    155 }
    156 
    157 }  // namespace mozilla::dom