xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/adapter/header_validator.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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