| // Copyright 2015 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef COBALT_CSP_PARSERS_H_ |
| #define COBALT_CSP_PARSERS_H_ |
| |
| #include <string> |
| #include <utility> |
| |
| #include "base/string_util.h" |
| #include "cobalt/csp/crypto.h" |
| |
| // Utilities for parsing CSP directive headers. These emulate similar |
| // string helpers from Blink source. |
| |
| namespace cobalt { |
| namespace csp { |
| |
| typedef std::pair<uint32, DigestValue> HashValue; |
| |
| enum ReferrerPolicy { |
| // https://w3c.github.io/webappsec/specs/referrer-policy/#referrer-policy-state-unsafe-url |
| kReferrerPolicyUnsafeUrl, |
| // The default policy, if no policy is explicitly set by the page. |
| kReferrerPolicyDefault, |
| // https://w3c.github.io/webappsec/specs/referrer-policy/#referrer-policy-state-no-referrer-when-downgrade |
| kReferrerPolicyNoReferrerWhenDowngrade, |
| // https://w3c.github.io/webappsec/specs/referrer-policy/#referrer-policy-state-no-referrer |
| kReferrerPolicyNoReferrer, |
| // https://w3c.github.io/webappsec/specs/referrer-policy/#referrer-policy-state-origin |
| kReferrerPolicyOrigin, |
| // https://w3c.github.io/webappsec/specs/referrer-policy/#referrer-policy-state-origin-when-cross-origin |
| kReferrerPolicyOriginWhenCrossOrigin, |
| }; |
| |
| enum ReflectedXSSDisposition { |
| kReflectedXSSUnset = 0, |
| kAllowReflectedXSS, |
| kReflectedXSSInvalid, |
| kFilterReflectedXSS, |
| kBlockReflectedXSS |
| }; |
| |
| enum HeaderType { kHeaderTypeReport, kHeaderTypeEnforce }; |
| |
| enum HeaderSource { |
| kHeaderSourceHTTP, |
| kHeaderSourceMeta, |
| kHeaderSourceMetaOutsideHead |
| }; |
| |
| inline bool SkipExactly(const char** position_ptr, const char* end, |
| char delimiter) { |
| const char*& position = *position_ptr; |
| if (position < end && *position == delimiter) { |
| ++position; |
| return true; |
| } |
| return false; |
| } |
| |
| template <bool CharacterPredicate(char)> |
| inline bool SkipExactly(const char** position_ptr, const char* end) { |
| const char*& position = *position_ptr; |
| if (position < end && CharacterPredicate(*position)) { |
| ++position; |
| return true; |
| } |
| return false; |
| } |
| |
| inline bool SkipToken(const char** position_ptr, const char* end, |
| const char* token) { |
| const char*& position = *position_ptr; |
| const char* current = position; |
| while (current < end && *token) { |
| if (*current != *token) { |
| return false; |
| } |
| ++current; |
| ++token; |
| } |
| if (*token) { |
| return false; |
| } |
| |
| position = current; |
| return true; |
| } |
| |
| inline void SkipUntil(const char** position_ptr, const char* end, |
| char delimiter) { |
| const char*& position = *position_ptr; |
| while (position < end && *position != delimiter) { |
| ++position; |
| } |
| } |
| |
| template <bool CharacterPredicate(char)> |
| inline void SkipUntil(const char** position_ptr, const char* end) { |
| const char*& position = *position_ptr; |
| while (position < end && !CharacterPredicate(*position)) { |
| ++position; |
| } |
| } |
| |
| template <bool CharacterPredicate(char)> |
| inline void SkipWhile(const char** position_ptr, const char* end) { |
| const char*& position = *position_ptr; |
| while (position < end && CharacterPredicate(*position)) { |
| ++position; |
| } |
| } |
| |
| template <bool CharacterPredicate(char)> |
| inline void ReverseSkipWhile(const char** position_ptr, const char* start) { |
| const char*& position = *position_ptr; |
| while (position >= start && CharacterPredicate(*position)) { |
| --position; |
| } |
| } |
| |
| inline bool IsNotAsciiWhitespace(char c) { return !IsAsciiWhitespace(c); } |
| |
| inline bool IsAsciiAlphanumeric(char c) { |
| return IsAsciiAlpha(c) || IsAsciiDigit(c); |
| } |
| |
| inline bool IsCSPDirectiveNameCharacter(char c) { |
| return IsAsciiAlphanumeric(c) || c == '-'; |
| } |
| |
| inline bool IsCSPDirectiveValueCharacter(char c) { |
| return IsAsciiWhitespace(c) || |
| (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR |
| } |
| |
| // Only checks for general Base64(url) encoded chars, not '=' chars since '=' is |
| // positional and may only appear at the end of a Base64 encoded string. |
| inline bool IsBase64EncodedCharacter(char c) { |
| return IsAsciiAlphanumeric(c) || c == '+' || c == '/' || c == '-' || c == '_'; |
| } |
| |
| inline bool IsNonceCharacter(char c) { |
| return IsBase64EncodedCharacter(c) || c == '='; |
| } |
| |
| inline bool IsSourceCharacter(char c) { return IsNotAsciiWhitespace(c); } |
| |
| inline bool IsPathComponentCharacter(char c) { return c != '?' && c != '#'; } |
| |
| inline bool IsHostCharacter(char c) { |
| return IsAsciiAlphanumeric(c) || c == '-'; |
| } |
| |
| inline bool IsSchemeContinuationCharacter(char c) { |
| return IsAsciiAlphanumeric(c) || c == '+' || c == '-' || c == '.'; |
| } |
| |
| inline bool IsNotColonOrSlash(char c) { return c != ':' && c != '/'; } |
| |
| inline bool IsMediaTypeCharacter(char c) { |
| return IsNotAsciiWhitespace(c) && c != '/'; |
| } |
| |
| static inline std::string ToString(const char* begin, const char* end) { |
| return std::string(begin, static_cast<size_t>(end - begin)); |
| } |
| |
| } // namespace csp |
| } // namespace cobalt |
| |
| #endif // COBALT_CSP_PARSERS_H_ |