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/. */
7 #ifndef nsCSPParser_h___
8 #define nsCSPParser_h___
10 #include "nsCSPUtils.h"
11 #include "nsCSPContext.h"
13 #include "PolicyTokenizer.h"
15 bool isNumberToken(char16_t aSymbol
);
16 bool isValidHexDig(char16_t aHexDig
);
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
= '@';
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.
52 static nsCSPPolicy
* parseContentSecurityPolicy(const nsAString
& aPolicyString
,
55 nsCSPContext
* aCSPContext
,
56 bool aDeliveredViaMetaTag
,
57 bool aSuppressLogMessages
);
60 nsCSPParser(policyTokens
& aTokens
, nsIURI
* aSelfURI
,
61 nsCSPContext
* aCSPContext
, bool aDeliveredViaMetaTag
,
62 bool aSuppressLogMessages
);
66 // Parsing the CSP using the source-list from
67 // http://www.w3.org/TR/CSP11/#source-list
68 nsCSPPolicy
* policy();
70 nsCSPDirective
* directiveName();
71 void directiveValue(nsTArray
<nsCSPBaseSrc
*>& outSrcs
);
72 void referrerDirectiveValue(nsCSPDirective
* aDir
);
73 void reportURIList(nsCSPDirective
* aDir
);
74 void sandboxFlagList(nsCSPDirective
* aDir
);
75 void sourceList(nsTArray
<nsCSPBaseSrc
*>& outSrcs
);
76 nsCSPBaseSrc
* sourceExpression();
77 nsCSPSchemeSrc
* schemeSource();
78 nsCSPHostSrc
* hostSource();
79 nsCSPBaseSrc
* keywordSource();
80 nsCSPNonceSrc
* nonceSource();
81 nsCSPHashSrc
* hashSource();
86 bool path(nsCSPHostSrc
* aCspHost
);
88 bool subHost(); // helper function to parse subDomains
89 bool atValidUnreservedChar(); // helper function to parse unreserved
90 bool atValidSubDelimChar(); // helper function to parse sub-delims
91 bool atValidPctEncodedChar(); // helper function to parse pct-encoded
92 bool subPath(nsCSPHostSrc
* aCspHost
); // helper function to parse paths
94 inline bool atEnd() { return mCurChar
>= mEndChar
; }
96 inline bool accept(char16_t aSymbol
) {
100 return (*mCurChar
== aSymbol
) && advance();
103 inline bool accept(bool (*aClassifier
)(char16_t
)) {
107 return (aClassifier(*mCurChar
)) && advance();
110 inline bool peek(char16_t aSymbol
) {
114 return *mCurChar
== aSymbol
;
117 inline bool peek(bool (*aClassifier
)(char16_t
)) {
121 return aClassifier(*mCurChar
);
124 inline bool advance() {
128 mCurValue
.Append(*mCurChar
++);
132 inline void resetCurValue() { mCurValue
.Truncate(); }
135 bool atValidPathChar();
137 void resetCurChar(const nsAString
& aToken
);
139 void logWarningErrorToConsole(uint32_t aSeverityFlag
, const char* aProperty
,
140 const nsTArray
<nsString
>& aParams
);
142 void MaybeWarnAboutIgnoredSources(const nsTArray
<nsCSPBaseSrc
*>& aSrcs
);
143 void MaybeWarnAboutUnsafeInline(const nsCSPDirective
& aDirective
);
144 void MaybeWarnAboutUnsafeEval(const nsCSPDirective
& aDirective
);
147 * When parsing the policy, the parser internally uses the following helper
148 * variables/members which are used/reset during parsing. The following
149 * example explains how they are used.
150 * The tokenizer separats all input into arrays of arrays of strings, which
151 * are stored in mTokens, for example:
152 * mTokens = [ [ script-src, http://www.example.com, 'self' ], ... ]
154 * When parsing starts, mCurdir always holds the currently processed array of
157 * mCurDir = [ script-src, http://www.example.com, 'self' ]
159 * During parsing, we process/consume one string at a time of that array.
160 * We set mCurToken to the string we are currently processing; in the first
161 * case that would be: mCurToken = script-src which allows to do simple string
162 * comparisons to see if mCurToken is a valid directive.
164 * Continuing parsing, the parser consumes the next string of that array,
166 * mCurToken = "http://www.example.com"
168 * mCurChar mEndChar (points *after* the 'm')
171 * After calling advance() the first time, helpers would hold the following
173 * mCurToken = "http://www.example.com"
175 * mCurChar mEndChar (points *after* the 'm')
178 * We continue parsing till all strings of one directive are consumed, then we
179 * reset mCurDir to hold the next array of strings and start the process all
183 const char16_t
* mCurChar
;
184 const char16_t
* mEndChar
;
187 nsTArray
<nsString
> mCurDir
;
189 // helpers to allow invalidation of srcs within script-src and style-src
190 // if either 'strict-dynamic' or at least a hash or nonce is present.
191 bool mHasHashOrNonce
; // false, if no hash or nonce is defined
192 bool mHasAnyUnsafeEval
; // false, if no (wasm-)unsafe-eval keyword is used.
193 bool mStrictDynamic
; // false, if 'strict-dynamic' is not defined
194 nsCSPKeywordSrc
* mUnsafeInlineKeywordSrc
; // null, otherwise invlidate()
196 // cache variables for child-src, frame-src and worker-src handling;
197 // in CSP 3 child-src is deprecated. For backwards compatibility
198 // child-src needs to restrict:
199 // (*) frames, in case frame-src is not expicitly specified
200 // (*) workers, in case worker-src is not expicitly specified
201 // If neither worker-src, nor child-src is present, then script-src
202 // needs to govern workers.
203 nsCSPChildSrcDirective
* mChildSrc
;
204 nsCSPDirective
* mFrameSrc
;
205 nsCSPDirective
* mWorkerSrc
;
206 nsCSPScriptSrcDirective
* mScriptSrc
;
207 nsCSPStyleSrcDirective
* mStyleSrc
;
209 // cache variable to let nsCSPHostSrc know that it's within
210 // the frame-ancestors directive.
211 bool mParsingFrameAncestorsDir
;
213 policyTokens mTokens
;
215 nsCSPPolicy
* mPolicy
;
216 nsCSPContext
* mCSPContext
; // used for console logging
217 bool mDeliveredViaMetaTag
;
218 bool mSuppressLogMessages
;
221 #endif /* nsCSPParser_h___ */