tor-browser

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

FeaturePolicy.h (8217B)


      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 #ifndef mozilla_dom_FeaturePolicy_h
      8 #define mozilla_dom_FeaturePolicy_h
      9 
     10 #include "nsCycleCollectionParticipant.h"
     11 #include "nsIPrincipal.h"
     12 #include "nsStringFwd.h"
     13 #include "nsTArray.h"
     14 #include "nsWrapperCache.h"
     15 
     16 /**
     17 * FeaturePolicy
     18 * ~~~~~~~~~~~~~
     19 *
     20 * Each document and each HTMLIFrameElement have a FeaturePolicy object which is
     21 * used to allow or deny features in their contexts.
     22 *
     23 * FeaturePolicy is composed by a set of directives configured by the
     24 * 'Feature-Policy' HTTP Header and the 'allow' attribute in HTMLIFrameElements.
     25 * Both header and attribute are parsed by FeaturePolicyParser which returns an
     26 * array of Feature objects. Each Feature object has a feature name and one of
     27 * these policies:
     28 * - eNone - the feature is fully disabled.
     29 * - eAll - the feature is allowed.
     30 * - eAllowList - the feature is allowed for a list of origins.
     31 *
     32 * An interesting element of FeaturePolicy is the inheritance: each context
     33 * inherits the feature-policy directives from the parent context, if it exists.
     34 * When a context inherits a policy for feature X, it only knows if that feature
     35 * is allowed or denied (it ignores the list of allowed origins for instance).
     36 * This information is stored in an array of inherited feature strings because
     37 * we care only to know when they are denied.
     38 *
     39 * FeaturePolicy can be reset if the 'allow' or 'src' attributes change in
     40 * HTMLIFrameElements. 'src' attribute is important to compute correcly
     41 * the features via FeaturePolicy 'src' keyword.
     42 *
     43 * When FeaturePolicy must decide if feature X is allowed or denied for the
     44 * current origin, it checks if the parent context denied that feature.
     45 * If not, it checks if there is a Feature object for that
     46 * feature named X and if the origin is allowed or not.
     47 *
     48 * From a C++ point of view, use FeaturePolicyUtils to obtain the list of
     49 * features and to check if they are allowed in the current context.
     50 *
     51 * dom.security.featurePolicy.header.enabled pref can be used to disable the
     52 * HTTP header support.
     53 **/
     54 
     55 class nsINode;
     56 
     57 namespace mozilla::dom {
     58 class Document;
     59 class BrowsingContext;
     60 class Feature;
     61 template <typename T>
     62 class Optional;
     63 
     64 class FeaturePolicyUtils;
     65 
     66 struct FeaturePolicyInfo final {
     67  CopyableTArray<nsString> mInheritedDeniedFeatureNames;
     68  CopyableTArray<nsString> mAttributeEnabledFeatureNames;
     69  nsString mDeclaredString;
     70  nsCOMPtr<nsIPrincipal> mDefaultOrigin;
     71  nsCOMPtr<nsIPrincipal> mSelfOrigin;
     72  nsCOMPtr<nsIPrincipal> mSrcOrigin;
     73 };
     74 
     75 using MaybeFeaturePolicyInfo = Maybe<FeaturePolicyInfo>;
     76 
     77 class FeaturePolicy final : public nsISupports, public nsWrapperCache {
     78  friend class FeaturePolicyUtils;
     79 
     80 public:
     81  NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL
     82  NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(FeaturePolicy)
     83 
     84  explicit FeaturePolicy(nsINode* aNode);
     85 
     86  // A FeaturePolicy must have a default origin.
     87  // This method must be called before any other exposed WebIDL method or before
     88  // checking if a feature is allowed.
     89  void SetDefaultOrigin(nsIPrincipal* aPrincipal) {
     90    mDefaultOrigin = aPrincipal;
     91  }
     92 
     93  void SetSrcOrigin(nsIPrincipal* aPrincipal) { mSrcOrigin = aPrincipal; }
     94 
     95  nsIPrincipal* DefaultOrigin() const { return mDefaultOrigin; }
     96 
     97  // Inherits the policy from the 'parent' context if it exists.
     98  void InheritPolicy(FeaturePolicy* aParentFeaturePolicy);
     99 
    100  // Inherits the policy from the 'parent' context if it exists.
    101  void InheritPolicy(const FeaturePolicyInfo& aContainerFeaturePolicyInfo);
    102 
    103  // Sets the declarative part of the policy. This can be from the HTTP header
    104  // or for the 'allow' HTML attribute.
    105  void SetDeclaredPolicy(mozilla::dom::Document* aDocument,
    106                         const nsAString& aPolicyString,
    107                         nsIPrincipal* aSelfOrigin, nsIPrincipal* aSrcOrigin);
    108 
    109  // This method creates a policy for aFeatureName allowing it to '*' if it
    110  // doesn't exist yet. It's used by HTMLIFrameElement to enable features by
    111  // attributes.
    112  void MaybeSetAllowedPolicy(const nsAString& aFeatureName);
    113 
    114  // Clears all the declarative policy directives. This is needed when the
    115  // 'allow' attribute or the 'src' attribute change for HTMLIFrameElement's
    116  // policy.
    117  void ResetDeclaredPolicy();
    118 
    119  // This method appends a feature to in-chain declared allowlist. If the name's
    120  // feature existed in the list, we only need to append the allowlist of new
    121  // feature to the existed one.
    122  void AppendToDeclaredAllowInAncestorChain(const Feature& aFeature);
    123 
    124  // This method returns true if aFeatureName is declared as "*" (allow all)
    125  // in parent.
    126  bool HasFeatureUnsafeAllowsAll(const nsAString& aFeatureName) const;
    127 
    128  // This method returns true if the aFeatureName is allowed for aOrigin
    129  // explicitly in ancestor chain,
    130  bool AllowsFeatureExplicitlyInAncestorChain(const nsAString& aFeatureName,
    131                                              nsIPrincipal* aOrigin) const;
    132 
    133  bool IsSameOriginAsSrc(nsIPrincipal* aPrincipal) const;
    134 
    135  // WebIDL internal methods.
    136 
    137  JSObject* WrapObject(JSContext* aCx,
    138                       JS::Handle<JSObject*> aGivenProto) override;
    139 
    140  nsINode* GetParentObject() const { return mParentNode; }
    141 
    142  // WebIDL explosed methods.
    143 
    144  bool AllowsFeature(const nsAString& aFeatureName,
    145                     const Optional<nsAString>& aOrigin) const;
    146 
    147  void Features(nsTArray<nsString>& aFeatures);
    148 
    149  void AllowedFeatures(nsTArray<nsString>& aAllowedFeatures);
    150 
    151  void GetAllowlistForFeature(const nsAString& aFeatureName,
    152                              nsTArray<nsString>& aList) const;
    153 
    154  const nsTArray<nsString>& InheritedDeniedFeatureNames() const {
    155    return mInheritedDeniedFeatureNames;
    156  }
    157 
    158  const nsTArray<nsString>& AttributeEnabledFeatureNames() const {
    159    return mAttributeEnabledFeatureNames;
    160  }
    161 
    162  void SetInheritedDeniedFeatureNames(
    163      const nsTArray<nsString>& aInheritedDeniedFeatureNames) {
    164    mInheritedDeniedFeatureNames = aInheritedDeniedFeatureNames.Clone();
    165  }
    166 
    167  const nsAString& DeclaredString() const { return mDeclaredString; }
    168 
    169  nsIPrincipal* GetSelfOrigin() const { return mSelfOrigin; }
    170  nsIPrincipal* GetSrcOrigin() const { return mSrcOrigin; }
    171 
    172  FeaturePolicyInfo ToFeaturePolicyInfo() const;
    173 
    174 private:
    175  ~FeaturePolicy() = default;
    176 
    177  // This method returns true if the aFeatureName is allowed for aOrigin,
    178  // following the feature-policy directives. See the comment at the top of this
    179  // file.
    180  bool AllowsFeatureInternal(const nsAString& aFeatureName,
    181                             nsIPrincipal* aOrigin) const;
    182 
    183  // Inherits a single denied feature from the parent context.
    184  void SetInheritedDeniedFeature(const nsAString& aFeatureName);
    185 
    186  bool HasInheritedDeniedFeature(const nsAString& aFeatureName) const;
    187 
    188  // This returns true if we have a declared feature policy for aFeatureName.
    189  bool HasDeclaredFeature(const nsAString& aFeatureName) const;
    190 
    191  nsINode* mParentNode;
    192 
    193  // This is set in sub-contexts when the parent blocks some feature for the
    194  // current context.
    195  nsTArray<nsString> mInheritedDeniedFeatureNames;
    196 
    197  // The list of features that have been enabled via MaybeSetAllowedPolicy.
    198  nsTArray<nsString> mAttributeEnabledFeatureNames;
    199 
    200  // This is set of feature names when the parent allows all for that feature.
    201  nsTArray<nsString> mParentAllowedAllFeatures;
    202 
    203  // The explicitly declared policy contains allowlist as a set of origins
    204  // except 'none' and '*'. This set contains all explicitly declared policies
    205  // in ancestor chain
    206  nsTArray<Feature> mDeclaredFeaturesInAncestorChain;
    207 
    208  // Feature policy for the current context.
    209  nsTArray<Feature> mFeatures;
    210 
    211  // Declared string represents Feature policy.
    212  nsString mDeclaredString;
    213 
    214  nsCOMPtr<nsIPrincipal> mDefaultOrigin;
    215  nsCOMPtr<nsIPrincipal> mSelfOrigin;
    216  nsCOMPtr<nsIPrincipal> mSrcOrigin;
    217 };
    218 
    219 }  // namespace mozilla::dom
    220 
    221 #endif  // mozilla_dom_FeaturePolicy_h