Coverage Report

Created: 2018-09-25 14:53

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