Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  FeaturePolicy.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "FeaturePolicy.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/Feature.h"
#include "mozilla/dom/FeaturePolicyBinding.h"
#include "mozilla/dom/FeaturePolicyParser.h"
#include "mozilla/dom/FeaturePolicyUtils.h"
#include "mozilla/dom/HTMLIFrameElement.h"
#include "mozilla/StaticPrefs_dom.h"
#include "nsContentUtils.h"
#include "nsNetUtil.h"

namespace mozilla::dom {

NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FeaturePolicy)
NS_IMPL_CYCLE_COLLECTING_ADDREF(FeaturePolicy)
NS_IMPL_CYCLE_COLLECTING_RELEASE(FeaturePolicy)

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FeaturePolicy)
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END

FeaturePolicy::FeaturePolicy(nsINode* aNode) : mParentNode(aNode) {}

void FeaturePolicy::InheritPolicy(FeaturePolicy* aParentPolicy) {
  MOZ_ASSERT(aParentPolicy);

  mInheritedDeniedFeatureNames.Clear();

  RefPtr<FeaturePolicy> dest = this;
  RefPtr<FeaturePolicy> src = aParentPolicy;

  // Inherit origins which explicitly declared policy in chain
  for (const Feature& featureInChain :
       aParentPolicy->mDeclaredFeaturesInAncestorChain) {
    dest->AppendToDeclaredAllowInAncestorChain(featureInChain);
  }

  FeaturePolicyUtils::ForEachFeature([dest, src](const char* aFeatureName) {
    nsString featureName;
    featureName.AppendASCII(aFeatureName);
    // Store unsafe allows all (allow=*)
    if (src->HasFeatureUnsafeAllowsAll(featureName)) {
      dest->mParentAllowedAllFeatures.AppendElement(featureName);
    }

    // If the destination has a declared feature (via the HTTP header or 'allow'
    // attribute) we allow the feature if the destination allows it and the
    // parent allows its origin or the destinations' one.
    if (dest->HasDeclaredFeature(featureName) &&
        dest->AllowsFeatureInternal(featureName, dest->mDefaultOrigin)) {
      if (!src->AllowsFeatureInternal(featureName, src->mDefaultOrigin) &&
          !src->AllowsFeatureInternal(featureName, dest->mDefaultOrigin)) {
        dest->SetInheritedDeniedFeature(featureName);
      }
      return;
    }

    // If there was not a declared feature, we allow the feature if the parent
    // FeaturePolicy allows the current origin.
    if (!src->AllowsFeatureInternal(featureName, dest->mDefaultOrigin)) {
      dest->SetInheritedDeniedFeature(featureName);
    }
  });
}

void FeaturePolicy::InheritPolicy(
    const FeaturePolicyInfo& aContainerFeaturePolicyInfo) {
  // We create a temporary FeaturePolicy from the FeaturePolicyInfo to be able
  // to re-use the inheriting functionality from FeaturePolicy.
  RefPtr<dom::FeaturePolicy> featurePolicy = new dom::FeaturePolicy(nullptr);
  featurePolicy->SetDefaultOrigin(aContainerFeaturePolicyInfo.mDefaultOrigin);
  featurePolicy->SetInheritedDeniedFeatureNames(
      aContainerFeaturePolicyInfo.mInheritedDeniedFeatureNames);

  const auto& declaredString = aContainerFeaturePolicyInfo.mDeclaredString;
  if (aContainerFeaturePolicyInfo.mSelfOrigin && !declaredString.IsEmpty()) {
    featurePolicy->SetDeclaredPolicy(nullptr, declaredString,
                                     aContainerFeaturePolicyInfo.mSelfOrigin,
                                     aContainerFeaturePolicyInfo.mSrcOrigin);
  }

  for (const auto& featureName :
       aContainerFeaturePolicyInfo.mAttributeEnabledFeatureNames) {
    featurePolicy->MaybeSetAllowedPolicy(featureName);
  }

  InheritPolicy(featurePolicy);
}

void FeaturePolicy::SetInheritedDeniedFeature(const nsAString& aFeatureName) {
  MOZ_ASSERT(!HasInheritedDeniedFeature(aFeatureName));
  mInheritedDeniedFeatureNames.AppendElement(aFeatureName);
}

bool FeaturePolicy::HasInheritedDeniedFeature(
    const nsAString& aFeatureName) const {
  return mInheritedDeniedFeatureNames.Contains(aFeatureName);
}

bool FeaturePolicy::HasDeclaredFeature(const nsAString& aFeatureName) const {
  for (const Feature& feature : mFeatures) {
    if (feature.Name().Equals(aFeatureName)) {
      return true;
    }
  }

  return false;
}

bool FeaturePolicy::HasFeatureUnsafeAllowsAll(
    const nsAString& aFeatureName) const {
  for (const Feature& feature : mFeatures) {
    if (feature.AllowsAll() && feature.Name().Equals(aFeatureName)) {
      return true;
    }
  }

  // We should look into parent too (for example, document of iframe which
  // allows all, would be unsafe)
  return mParentAllowedAllFeatures.Contains(aFeatureName);
}

void FeaturePolicy::AppendToDeclaredAllowInAncestorChain(
    const Feature& aFeature) {
  for (Feature& featureInChain : mDeclaredFeaturesInAncestorChain) {
    if (featureInChain.Name().Equals(aFeature.Name())) {
      MOZ_ASSERT(featureInChain.HasAllowList());

      nsTArray<nsCOMPtr<nsIPrincipal>> list;
      aFeature.GetAllowList(list);

      for (nsIPrincipal* principal : list) {
        featureInChain.AppendToAllowList(principal);
      }
      continue;
    }
  }

  mDeclaredFeaturesInAncestorChain.AppendElement(aFeature);
}

bool FeaturePolicy::IsSameOriginAsSrc(nsIPrincipal* aPrincipal) const {
  MOZ_ASSERT(aPrincipal);

  if (!mSrcOrigin) {
    return false;
  }

  return BasePrincipal::Cast(mSrcOrigin)
      ->Subsumes(aPrincipal, BasePrincipal::ConsiderDocumentDomain);
}

void FeaturePolicy::SetDeclaredPolicy(Document* aDocument,
                                      const nsAString& aPolicyString,
                                      nsIPrincipal* aSelfOrigin,
                                      nsIPrincipal* aSrcOrigin) {
  ResetDeclaredPolicy();

  mDeclaredString = aPolicyString;
  mSelfOrigin = aSelfOrigin;
  mSrcOrigin = aSrcOrigin;

  Unused << NS_WARN_IF(!FeaturePolicyParser::ParseString(
      aPolicyString, aDocument, aSelfOrigin, aSrcOrigin, mFeatures));

  // Only store explicitly declared allowlist
  for (const Feature& feature : mFeatures) {
    if (feature.HasAllowList()) {
      AppendToDeclaredAllowInAncestorChain(feature);
    }
  }
}

void FeaturePolicy::ResetDeclaredPolicy() {
  mFeatures.Clear();
  mDeclaredString.Truncate();
  mSelfOrigin = nullptr;
  mSrcOrigin = nullptr;
  mDeclaredFeaturesInAncestorChain.Clear();
  mAttributeEnabledFeatureNames.Clear();
}

JSObject* FeaturePolicy::WrapObject(JSContext* aCx,
                                    JS::Handle<JSObject*> aGivenProto) {
  return FeaturePolicy_Binding::Wrap(aCx, this, aGivenProto);
}

bool FeaturePolicy::AllowsFeature(const nsAString& aFeatureName,
                                  const Optional<nsAString>& aOrigin) const {
  nsCOMPtr<nsIPrincipal> origin;
  if (aOrigin.WasPassed()) {
    nsCOMPtr<nsIURI> uri;
    nsresult rv = NS_NewURI(getter_AddRefs(uri), aOrigin.Value());
    if (NS_FAILED(rv)) {
      return false;
    }
    origin = BasePrincipal::CreateContentPrincipal(
        uri, BasePrincipal::Cast(mDefaultOrigin)->OriginAttributesRef());
  } else {
    origin = mDefaultOrigin;
  }

  if (NS_WARN_IF(!origin)) {
    return false;
  }

  return AllowsFeatureInternal(aFeatureName, origin);
}

bool FeaturePolicy::AllowsFeatureExplicitlyInAncestorChain(
    const nsAString& aFeatureName, nsIPrincipal* aOrigin) const {
  MOZ_ASSERT(aOrigin);

  for (const Feature& feature : mDeclaredFeaturesInAncestorChain) {
    if (feature.Name().Equals(aFeatureName)) {
      return feature.AllowListContains(aOrigin);
    }
  }

  return false;
}

bool FeaturePolicy::AllowsFeatureInternal(const nsAString& aFeatureName,
                                          nsIPrincipal* aOrigin) const {
  MOZ_ASSERT(aOrigin);

  // Let's see if have to disable this feature because inherited policy.
  if (HasInheritedDeniedFeature(aFeatureName)) {
    return false;
  }

  for (const Feature& feature : mFeatures) {
    if (feature.Name().Equals(aFeatureName)) {
      return feature.Allows(aOrigin);
    }
  }

  switch (FeaturePolicyUtils::DefaultAllowListFeature(aFeatureName)) {
    case FeaturePolicyUtils::FeaturePolicyValue::eAll:
      return true;

    case FeaturePolicyUtils::FeaturePolicyValue::eSelf:
      return BasePrincipal::Cast(mDefaultOrigin)
          ->Subsumes(aOrigin, BasePrincipal::ConsiderDocumentDomain);

    case FeaturePolicyUtils::FeaturePolicyValue::eNone:
      return false;

    default:
      MOZ_CRASH("Unknown default value");
  }

  return false;
}

void FeaturePolicy::Features(nsTArray<nsString>& aFeatures) {
  RefPtr<FeaturePolicy> self = this;
  FeaturePolicyUtils::ForEachFeature(
      [self, &aFeatures](const char* aFeatureName) {
        nsString featureName;
        featureName.AppendASCII(aFeatureName);
        aFeatures.AppendElement(featureName);
      });
}

void FeaturePolicy::AllowedFeatures(nsTArray<nsString>& aAllowedFeatures) {
  RefPtr<FeaturePolicy> self = this;
  FeaturePolicyUtils::ForEachFeature(
      [self, &aAllowedFeatures](const char* aFeatureName) {
        nsString featureName;
        featureName.AppendASCII(aFeatureName);

        if (self->AllowsFeatureInternal(featureName, self->mDefaultOrigin)) {
          aAllowedFeatures.AppendElement(featureName);
        }
      });
}

void FeaturePolicy::GetAllowlistForFeature(const nsAString& aFeatureName,
                                           nsTArray<nsString>& aList) const {
  if (!AllowsFeatureInternal(aFeatureName, mDefaultOrigin)) {
    return;
  }

  for (const Feature& feature : mFeatures) {
    if (feature.Name().Equals(aFeatureName)) {
      if (feature.AllowsAll()) {
        aList.AppendElement(u"*"_ns);
        return;
      }

      nsTArray<nsCOMPtr<nsIPrincipal>> list;
      feature.GetAllowList(list);

      for (nsIPrincipal* principal : list) {
        nsAutoCString originNoSuffix;
        nsresult rv = principal->GetOriginNoSuffix(originNoSuffix);
        if (NS_WARN_IF(NS_FAILED(rv))) {
          return;
        }

        aList.AppendElement(NS_ConvertUTF8toUTF16(originNoSuffix));
      }
      return;
    }
  }

  switch (FeaturePolicyUtils::DefaultAllowListFeature(aFeatureName)) {
    case FeaturePolicyUtils::FeaturePolicyValue::eAll:
      aList.AppendElement(u"*"_ns);
      return;

    case FeaturePolicyUtils::FeaturePolicyValue::eSelf: {
      nsAutoCString originNoSuffix;
      nsresult rv = mDefaultOrigin->GetOriginNoSuffix(originNoSuffix);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return;
      }

      aList.AppendElement(NS_ConvertUTF8toUTF16(originNoSuffix));
      return;
    }

    case FeaturePolicyUtils::FeaturePolicyValue::eNone:
      return;

    default:
      MOZ_CRASH("Unknown default value");
  }
}

void FeaturePolicy::MaybeSetAllowedPolicy(const nsAString& aFeatureName) {
  MOZ_ASSERT(FeaturePolicyUtils::IsSupportedFeature(aFeatureName) ||
             FeaturePolicyUtils::IsExperimentalFeature(aFeatureName));
  // Skip if feature is in experimental phase
  if (!StaticPrefs::dom_security_featurePolicy_experimental_enabled() &&
      FeaturePolicyUtils::IsExperimentalFeature(aFeatureName)) {
    return;
  }

  if (HasDeclaredFeature(aFeatureName)) {
    return;
  }

  Feature feature(aFeatureName);
  feature.SetAllowsAll();

  mFeatures.AppendElement(feature);
  mAttributeEnabledFeatureNames.AppendElement(aFeatureName);
}

FeaturePolicyInfo FeaturePolicy::ToFeaturePolicyInfo() const {
  return {mInheritedDeniedFeatureNames.Clone(),
          mAttributeEnabledFeatureNames.Clone(),
          mDeclaredString,
          mDefaultOrigin,
          mSelfOrigin,
          mSrcOrigin};
}

}  // namespace mozilla::dom

Messung V0.5
C=97 H=89 G=93

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge