| #ifndef QUICHE_HTTP2_ADAPTER_HEADER_VALIDATOR_H_ | |
| #define QUICHE_HTTP2_ADAPTER_HEADER_VALIDATOR_H_ | |
| #include <bitset> | |
| #include <optional> | |
| #include <string> | |
| #include <vector> | |
| #include "absl/strings/string_view.h" | |
| #include "quiche/http2/adapter/header_validator_base.h" | |
| #include "quiche/common/platform/api/quiche_export.h" | |
| namespace http2 { | |
| namespace adapter { | |
| class QUICHE_EXPORT HeaderValidator : public HeaderValidatorBase { | |
| public: | |
| HeaderValidator() = default; | |
| void StartHeaderBlock() override; | |
| HeaderStatus ValidateSingleHeader(absl::string_view key, | |
| absl::string_view value) override; | |
| // Returns true if all required pseudoheaders and no extra pseudoheaders are | |
| // present for the given header type. | |
| bool FinishHeaderBlock(HeaderType type) override; | |
| // Returns whether `name` is valid according to RFC 9110 Section 5.1. | |
| // ':' is an invalid character, therefore HTTP/2 pseudo-headers must be | |
| // validated with the leading colon removed. | |
| static bool IsValidHeaderName(absl::string_view name); | |
| // Returns whether `value` is valid according to RFC 9110 Section 5.5 and | |
| // RFC 9113 Section 8.2.1. | |
| static bool IsValidHeaderValue(absl::string_view value, | |
| ObsTextOption ops_text_option); | |
| // Returns whether `authority` is valid according to RFC 3986 Section 3.2. | |
| static bool IsValidAuthority(absl::string_view authority); | |
| // Returns whether `path` is valid according to RFC 3986 Section 3.3. May | |
| // contain the query part of a URI. | |
| static bool IsValidPath(absl::string_view path, bool allow_fragment); | |
| private: | |
| enum ContentLengthStatus : uint8_t { | |
| CONTENT_LENGTH_OK, | |
| CONTENT_LENGTH_SKIP, // Used to handle duplicate content length values. | |
| CONTENT_LENGTH_ERROR, | |
| }; | |
| ContentLengthStatus HandleContentLength(absl::string_view value); | |
| bool ValidateAndSetAuthority(absl::string_view authority); | |
| enum PseudoHeaderTag : uint8_t { | |
| TAG_AUTHORITY = 0, | |
| TAG_METHOD, | |
| TAG_PATH, | |
| TAG_PROTOCOL, | |
| TAG_SCHEME, | |
| TAG_STATUS, | |
| TAG_UNKNOWN_EXTRA, | |
| TAG_ENUM_SIZE, | |
| }; | |
| void RecordPseudoHeader(PseudoHeaderTag tag); | |
| using PseudoHeaderTagSet = std::bitset<TAG_ENUM_SIZE>; | |
| enum PseudoHeaderState : uint8_t { | |
| STATE_AUTHORITY_IS_NONEMPTY, | |
| STATE_METHOD_IS_OPTIONS, | |
| STATE_METHOD_IS_CONNECT, | |
| STATE_PATH_IS_EMPTY, | |
| STATE_PATH_IS_STAR, | |
| STATE_PATH_INITIAL_SLASH, | |
| STATE_ENUM_SIZE, | |
| }; | |
| using PseudoHeaderStateSet = std::bitset<STATE_ENUM_SIZE>; | |
| static bool ValidateRequestHeaders( | |
| const PseudoHeaderTagSet& pseudo_headers, | |
| const PseudoHeaderStateSet& pseudo_header_state, | |
| bool allow_extended_connect); | |
| static bool ValidateRequestTrailers(const PseudoHeaderTagSet& pseudo_headers); | |
| static bool ValidateResponseHeaders(const PseudoHeaderTagSet& pseudo_headers); | |
| static bool ValidateResponseTrailers( | |
| const PseudoHeaderTagSet& pseudo_headers); | |
| PseudoHeaderTagSet pseudo_headers_; | |
| PseudoHeaderStateSet pseudo_header_state_; | |
| std::string authority_; | |
| }; | |
| } // namespace adapter | |
| } // namespace http2 | |
| #endif // QUICHE_HTTP2_ADAPTER_HEADER_VALIDATOR_H_ |