tor-browser

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

nsCSPParser.h (8214B)


      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 nsCSPParser_h___
      8 #define nsCSPParser_h___
      9 
     10 #include "PolicyTokenizer.h"
     11 #include "nsCSPContext.h"
     12 #include "nsCSPUtils.h"
     13 #include "nsIURI.h"
     14 
     15 bool isNumberToken(char16_t aSymbol);
     16 bool isValidHexDig(char16_t aHexDig);
     17 
     18 // clang-format off
     19 const char16_t COLON        = ':';
     20 const char16_t SEMICOLON    = ';';
     21 const char16_t SLASH        = '/';
     22 const char16_t PLUS         = '+';
     23 const char16_t DASH         = '-';
     24 const char16_t DOT          = '.';
     25 const char16_t UNDERLINE    = '_';
     26 const char16_t TILDE        = '~';
     27 const char16_t WILDCARD     = '*';
     28 const char16_t SINGLEQUOTE  = '\'';
     29 const char16_t NUMBER_SIGN  = '#';
     30 const char16_t QUESTIONMARK = '?';
     31 const char16_t PERCENT_SIGN = '%';
     32 const char16_t EXCLAMATION  = '!';
     33 const char16_t DOLLAR       = '$';
     34 const char16_t AMPERSAND    = '&';
     35 const char16_t OPENBRACE    = '(';
     36 const char16_t CLOSINGBRACE = ')';
     37 const char16_t EQUALS       = '=';
     38 const char16_t ATSYMBOL     = '@';
     39 // clang-format on
     40 
     41 class nsCSPParser {
     42 public:
     43  /**
     44   * The CSP parser only has one publicly accessible function, which is
     45   * parseContentSecurityPolicy. Internally the input string is separated into
     46   * string tokens and policy() is called, which starts parsing the policy. The
     47   * parser calls one function after the other according the the source-list
     48   * from http://www.w3.org/TR/CSP11/#source-list. E.g., the parser can only
     49   * call port() after the parser has already processed any possible host in
     50   * host(), similar to a finite state machine.
     51   */
     52  static nsCSPPolicy* parseContentSecurityPolicy(const nsAString& aPolicyString,
     53                                                 nsIURI* aSelfURI,
     54                                                 bool aReportOnly,
     55                                                 nsCSPContext* aCSPContext,
     56                                                 bool aDeliveredViaMetaTag,
     57                                                 bool aSuppressLogMessages);
     58 
     59 private:
     60  nsCSPParser(policyTokens& aTokens, nsIURI* aSelfURI,
     61              nsCSPContext* aCSPContext, bool aDeliveredViaMetaTag,
     62              bool aSuppressLogMessages);
     63 
     64  ~nsCSPParser();
     65 
     66  // Parsing the CSP using the source-list from
     67  // http://www.w3.org/TR/CSP11/#source-list
     68  nsCSPPolicy* policy();
     69  void directive();
     70  nsCSPDirective* directiveName();
     71  void directiveValue(nsTArray<nsCSPBaseSrc*>& outSrcs);
     72  void referrerDirectiveValue(nsCSPDirective* aDir);
     73  void reportURIList(nsCSPDirective* aDir);
     74  void reportGroup(nsCSPDirective* aDir);
     75  void sandboxFlagList(nsCSPDirective* aDir);
     76  void handleRequireTrustedTypesForDirective(nsCSPDirective* aDir);
     77  void handleTrustedTypesDirective(nsCSPDirective* aDir);
     78  void sourceList(nsTArray<nsCSPBaseSrc*>& outSrcs);
     79  nsCSPBaseSrc* sourceExpression();
     80  nsCSPSchemeSrc* schemeSource();
     81  nsCSPHostSrc* hostSource();
     82  nsCSPBaseSrc* keywordSource();
     83  nsCSPNonceSrc* nonceSource();
     84  nsCSPHashSrc* hashSource();
     85  nsCSPHostSrc* host();
     86  bool hostChar();
     87  bool schemeChar();
     88  bool port();
     89  bool path(nsCSPHostSrc* aCspHost);
     90 
     91  bool subHost();                        // helper function to parse subDomains
     92  bool atValidUnreservedChar();          // helper function to parse unreserved
     93  bool atValidSubDelimChar();            // helper function to parse sub-delims
     94  bool atValidPctEncodedChar();          // helper function to parse pct-encoded
     95  bool subPath(nsCSPHostSrc* aCspHost);  // helper function to parse paths
     96 
     97  inline bool atEnd() { return mCurChar >= mEndChar; }
     98 
     99  inline bool accept(char16_t aSymbol) {
    100    if (atEnd()) {
    101      return false;
    102    }
    103    return (*mCurChar == aSymbol) && advance();
    104  }
    105 
    106  inline bool accept(bool (*aClassifier)(char16_t)) {
    107    if (atEnd()) {
    108      return false;
    109    }
    110    return (aClassifier(*mCurChar)) && advance();
    111  }
    112 
    113  inline bool peek(char16_t aSymbol) {
    114    if (atEnd()) {
    115      return false;
    116    }
    117    return *mCurChar == aSymbol;
    118  }
    119 
    120  inline bool peek(bool (*aClassifier)(char16_t)) {
    121    if (atEnd()) {
    122      return false;
    123    }
    124    return aClassifier(*mCurChar);
    125  }
    126 
    127  inline bool advance() {
    128    if (atEnd()) {
    129      return false;
    130    }
    131    mCurValue.Append(*mCurChar++);
    132    return true;
    133  }
    134 
    135  inline void resetCurValue() { mCurValue.Truncate(); }
    136 
    137  bool atEndOfPath();
    138  bool atValidPathChar();
    139 
    140  void resetCurChar(const nsAString& aToken);
    141 
    142  void logWarningErrorToConsole(uint32_t aSeverityFlag, const char* aProperty,
    143                                const nsTArray<nsString>& aParams);
    144 
    145  void logWarningForIgnoringNoneKeywordToConsole();
    146 
    147  void MaybeWarnAboutIgnoredSources(const nsTArray<nsCSPBaseSrc*>& aSrcs);
    148  void MaybeWarnAboutUnsafeInline(const nsCSPDirective& aDirective);
    149  void MaybeWarnAboutUnsafeEval(const nsCSPDirective& aDirective);
    150 
    151  /**
    152   * When parsing the policy, the parser internally uses the following helper
    153   * variables/members which are used/reset during parsing. The following
    154   * example explains how they are used.
    155   * The tokenizer separats all input into arrays of arrays of strings, which
    156   * are stored in mTokens, for example:
    157   *   mTokens = [ [ script-src, http://www.example.com, 'self' ], ... ]
    158   *
    159   * When parsing starts, mCurdir always holds the currently processed array of
    160   * strings.
    161   * In our example:
    162   *   mCurDir = [ script-src, http://www.example.com, 'self' ]
    163   *
    164   * During parsing, we process/consume one string at a time of that array.
    165   * We set mCurToken to the string we are currently processing; in the first
    166   * case that would be: mCurToken = script-src which allows to do simple string
    167   * comparisons to see if mCurToken is a valid directive.
    168   *
    169   * Continuing parsing, the parser consumes the next string of that array,
    170   * resetting:
    171   *   mCurToken = "http://www.example.com"
    172   *                ^                     ^
    173   *                mCurChar              mEndChar (points *after* the 'm')
    174   *   mCurValue = ""
    175   *
    176   * After calling advance() the first time, helpers would hold the following
    177   * values:
    178   *   mCurToken = "http://www.example.com"
    179   *                 ^                    ^
    180   *                 mCurChar             mEndChar (points *after* the 'm')
    181   *  mCurValue = "h"
    182   *
    183   * We continue parsing till all strings of one directive are consumed, then we
    184   * reset mCurDir to hold the next array of strings and start the process all
    185   * over.
    186   */
    187 
    188  const char16_t* mCurChar;
    189  const char16_t* mEndChar;
    190  nsString mCurValue;
    191  nsString mCurToken;
    192  nsTArray<nsString> mCurDir;
    193 
    194  // helpers to allow invalidation of srcs within script-src and style-src
    195  // if either 'strict-dynamic' or at least a hash or nonce is present.
    196  bool mHasHashOrNonce;    // false, if no hash or nonce is defined
    197  bool mHasAnyUnsafeEval;  // false, if no (wasm-)unsafe-eval keyword is used.
    198  bool mStrictDynamic;     // false, if 'strict-dynamic' is not defined
    199  nsCSPKeywordSrc* mUnsafeInlineKeywordSrc;  // null, otherwise invlidate()
    200 
    201  // cache variables for child-src, frame-src and worker-src handling;
    202  // in CSP 3 child-src is deprecated. For backwards compatibility
    203  // child-src needs to restrict:
    204  //   (*) frames, in case frame-src is not expicitly specified
    205  //   (*) workers, in case worker-src is not expicitly specified
    206  // If neither worker-src, nor child-src is present, then script-src
    207  // needs to govern workers.
    208  nsCSPChildSrcDirective* mChildSrc;
    209  nsCSPDirective* mFrameSrc;
    210  nsCSPDirective* mWorkerSrc;
    211  nsCSPScriptSrcDirective* mScriptSrc;
    212  nsCSPStyleSrcDirective* mStyleSrc;
    213 
    214  // cache variable to let nsCSPHostSrc know that it's within
    215  // the frame-ancestors directive.
    216  bool mParsingFrameAncestorsDir;
    217 
    218  policyTokens mTokens;
    219  nsIURI* mSelfURI;
    220  nsCSPPolicy* mPolicy;
    221  nsCSPContext* mCSPContext;  // used for console logging
    222  bool mDeliveredViaMetaTag;
    223  bool mSuppressLogMessages;
    224 };
    225 
    226 #endif /* nsCSPParser_h___ */