1 #ifndef QUICHE_HTTP2_ADAPTER_HEADER_VALIDATOR_H_ 2 #define QUICHE_HTTP2_ADAPTER_HEADER_VALIDATOR_H_ 3 4 #include <bitset> 5 #include <optional> 6 #include <string> 7 #include <vector> 8 9 #include "absl/strings/string_view.h" 10 #include "quiche/http2/adapter/header_validator_base.h" 11 #include "quiche/common/platform/api/quiche_export.h" 12 13 namespace http2 { 14 namespace adapter { 15 16 class QUICHE_EXPORT HeaderValidator : public HeaderValidatorBase { 17 public: 18 HeaderValidator() = default; 19 20 void StartHeaderBlock() override; 21 22 HeaderStatus ValidateSingleHeader(absl::string_view key, 23 absl::string_view value) override; 24 25 // Returns true if all required pseudoheaders and no extra pseudoheaders are 26 // present for the given header type. 27 bool FinishHeaderBlock(HeaderType type) override; 28 29 // Returns whether `name` is valid according to RFC 9110 Section 5.1. 30 // ':' is an invalid character, therefore HTTP/2 pseudo-headers must be 31 // validated with the leading colon removed. 32 static bool IsValidHeaderName(absl::string_view name); 33 34 // Returns whether `value` is valid according to RFC 9110 Section 5.5 and 35 // RFC 9113 Section 8.2.1. 36 static bool IsValidHeaderValue(absl::string_view value, 37 ObsTextOption ops_text_option); 38 39 // Returns whether `authority` is valid according to RFC 3986 Section 3.2. 40 static bool IsValidAuthority(absl::string_view authority); 41 42 // Returns whether `path` is valid according to RFC 3986 Section 3.3. May 43 // contain the query part of a URI. 44 static bool IsValidPath(absl::string_view path, bool allow_fragment); 45 46 private: 47 enum ContentLengthStatus { 48 CONTENT_LENGTH_OK, 49 CONTENT_LENGTH_SKIP, // Used to handle duplicate content length values. 50 CONTENT_LENGTH_ERROR, 51 }; 52 ContentLengthStatus HandleContentLength(absl::string_view value); 53 bool ValidateAndSetAuthority(absl::string_view authority); 54 55 enum PseudoHeaderTag { 56 TAG_AUTHORITY = 0, 57 TAG_METHOD, 58 TAG_PATH, 59 TAG_PROTOCOL, 60 TAG_SCHEME, 61 TAG_STATUS, 62 TAG_UNKNOWN_EXTRA, 63 TAG_ENUM_SIZE, 64 }; 65 void RecordPseudoHeader(PseudoHeaderTag tag); 66 67 using PseudoHeaderTagSet = std::bitset<TAG_ENUM_SIZE>; 68 69 enum PseudoHeaderState { 70 STATE_AUTHORITY_IS_NONEMPTY, 71 STATE_METHOD_IS_OPTIONS, 72 STATE_METHOD_IS_CONNECT, 73 STATE_PATH_IS_EMPTY, 74 STATE_PATH_IS_STAR, 75 STATE_PATH_INITIAL_SLASH, 76 STATE_ENUM_SIZE, 77 }; 78 using PseudoHeaderStateSet = std::bitset<STATE_ENUM_SIZE>; 79 80 static bool ValidateRequestHeaders( 81 const PseudoHeaderTagSet& pseudo_headers, 82 const PseudoHeaderStateSet& pseudo_header_state, 83 bool allow_extended_connect); 84 static bool ValidateRequestTrailers(const PseudoHeaderTagSet& pseudo_headers); 85 static bool ValidateResponseHeaders(const PseudoHeaderTagSet& pseudo_headers); 86 static bool ValidateResponseTrailers( 87 const PseudoHeaderTagSet& pseudo_headers); 88 89 PseudoHeaderTagSet pseudo_headers_; 90 PseudoHeaderStateSet pseudo_header_state_; 91 92 std::string authority_; 93 }; 94 95 } // namespace adapter 96 } // namespace http2 97 98 #endif // QUICHE_HTTP2_ADAPTER_HEADER_VALIDATOR_H_ 99