blob: 602940cdadf6fc86bf77294c00e428b5d5f9c797 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/chlo_extractor.h"
6
7#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
8#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
9#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
10#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
11#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
12#include "net/third_party/quiche/src/quic/core/quic_framer.h"
13#include "net/third_party/quiche/src/quic/core/quic_utils.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
16
17namespace quic {
18
19namespace {
20
21class ChloFramerVisitor : public QuicFramerVisitorInterface,
22 public CryptoFramerVisitorInterface {
23 public:
24 ChloFramerVisitor(QuicFramer* framer,
25 const QuicTagVector& create_session_tag_indicators,
26 ChloExtractor::Delegate* delegate);
27
28 ~ChloFramerVisitor() override = default;
29
30 // QuicFramerVisitorInterface implementation
31 void OnError(QuicFramer* framer) override {}
32 bool OnProtocolVersionMismatch(ParsedQuicVersion version,
33 PacketHeaderFormat form) override;
34 void OnPacket() override {}
35 void OnPublicResetPacket(const QuicPublicResetPacket& packet) override {}
36 void OnVersionNegotiationPacket(
37 const QuicVersionNegotiationPacket& packet) override {}
dschinazi244f6dc2019-05-06 15:45:16 -070038 void OnRetryPacket(QuicConnectionId original_connection_id,
39 QuicConnectionId new_connection_id,
40 QuicStringPiece retry_token) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050041 bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
42 bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
43 void OnDecryptedPacket(EncryptionLevel level) override {}
44 bool OnPacketHeader(const QuicPacketHeader& header) override;
45 void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
46 bool OnStreamFrame(const QuicStreamFrame& frame) override;
47 bool OnCryptoFrame(const QuicCryptoFrame& frame) override;
48 bool OnAckFrameStart(QuicPacketNumber largest_acked,
49 QuicTime::Delta ack_delay_time) override;
50 bool OnAckRange(QuicPacketNumber start, QuicPacketNumber end) override;
51 bool OnAckTimestamp(QuicPacketNumber packet_number,
52 QuicTime timestamp) override;
53 bool OnAckFrameEnd(QuicPacketNumber start) override;
54 bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
55 bool OnPingFrame(const QuicPingFrame& frame) override;
56 bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override;
57 bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050058 bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override;
59 bool OnRetireConnectionIdFrame(
60 const QuicRetireConnectionIdFrame& frame) override;
61 bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override;
62 bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
63 bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override;
64 bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
65 bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
fkastenholz3c4eabf2019-04-22 07:49:59 -070066 bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
67 bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050068 bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
69 bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
70 bool OnPaddingFrame(const QuicPaddingFrame& frame) override;
71 bool OnMessageFrame(const QuicMessageFrame& frame) override;
72 void OnPacketComplete() override {}
73 bool IsValidStatelessResetToken(QuicUint128 token) const override;
74 void OnAuthenticatedIetfStatelessResetPacket(
75 const QuicIetfStatelessResetPacket& packet) override {}
76
77 // CryptoFramerVisitorInterface implementation.
78 void OnError(CryptoFramer* framer) override;
79 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
80
81 // Shared implementation between OnStreamFrame and OnCryptoFrame.
82 bool OnHandshakeData(QuicStringPiece data);
83
84 bool found_chlo() { return found_chlo_; }
85 bool chlo_contains_tags() { return chlo_contains_tags_; }
86
87 private:
88 QuicFramer* framer_;
89 const QuicTagVector& create_session_tag_indicators_;
90 ChloExtractor::Delegate* delegate_;
91 bool found_chlo_;
92 bool chlo_contains_tags_;
93 QuicConnectionId connection_id_;
94};
95
96ChloFramerVisitor::ChloFramerVisitor(
97 QuicFramer* framer,
98 const QuicTagVector& create_session_tag_indicators,
99 ChloExtractor::Delegate* delegate)
100 : framer_(framer),
101 create_session_tag_indicators_(create_session_tag_indicators),
102 delegate_(delegate),
103 found_chlo_(false),
104 chlo_contains_tags_(false),
105 connection_id_(EmptyQuicConnectionId()) {}
106
107bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version,
108 PacketHeaderFormat /*form*/) {
109 if (!framer_->IsSupportedVersion(version)) {
110 return false;
111 }
112 framer_->set_version(version);
113 return true;
114}
115
116bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
117 const QuicPacketHeader& header) {
118 connection_id_ = header.destination_connection_id;
119 return true;
120}
121bool ChloFramerVisitor::OnUnauthenticatedHeader(
122 const QuicPacketHeader& header) {
123 return true;
124}
125bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& header) {
126 return true;
127}
128void ChloFramerVisitor::OnCoalescedPacket(const QuicEncryptedPacket& packet) {}
129bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700130 if (QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131 // CHLO will be sent in CRYPTO frames in v47 and above.
132 return false;
133 }
134 QuicStringPiece data(frame.data_buffer, frame.data_length);
135 if (frame.stream_id ==
136 QuicUtils::GetCryptoStreamId(framer_->transport_version()) &&
137 frame.offset == 0 && QuicTextUtils::StartsWith(data, "CHLO")) {
138 return OnHandshakeData(data);
139 }
140 return true;
141}
142
143bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700144 if (!QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145 // CHLO will be in stream frames before v47.
146 return false;
147 }
148 QuicStringPiece data(frame.data_buffer, frame.data_length);
149 if (frame.offset == 0 && QuicTextUtils::StartsWith(data, "CHLO")) {
150 return OnHandshakeData(data);
151 }
152 return true;
153}
154
155bool ChloFramerVisitor::OnHandshakeData(QuicStringPiece data) {
156 CryptoFramer crypto_framer;
157 crypto_framer.set_visitor(this);
158 if (!crypto_framer.ProcessInput(data)) {
159 return false;
160 }
161 // Interrogate the crypto framer and see if there are any
162 // intersecting tags between what we saw in the maybe-CHLO and the
163 // indicator set.
164 for (const QuicTag tag : create_session_tag_indicators_) {
165 if (crypto_framer.HasTag(tag)) {
166 chlo_contains_tags_ = true;
167 }
168 }
169 if (chlo_contains_tags_ && delegate_) {
170 // Unfortunately, because this is a partial CHLO,
171 // OnHandshakeMessage was never called, so the ALPN was never
172 // extracted. Fake it up a bit and send it to the delegate so that
173 // the correct dispatch can happen.
174 crypto_framer.ForceHandshake();
175 }
176
177 return true;
178}
179
180bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
181 QuicTime::Delta /*ack_delay_time*/) {
182 return true;
183}
184
185bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/,
186 QuicPacketNumber /*end*/) {
187 return true;
188}
189
190bool ChloFramerVisitor::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
191 QuicTime /*timestamp*/) {
192 return true;
193}
194
195bool ChloFramerVisitor::OnAckFrameEnd(QuicPacketNumber /*start*/) {
196 return true;
197}
198
199bool ChloFramerVisitor::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) {
200 return true;
201}
202
203bool ChloFramerVisitor::OnPingFrame(const QuicPingFrame& frame) {
204 return true;
205}
206
207bool ChloFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
208 return true;
209}
210
211bool ChloFramerVisitor::OnConnectionCloseFrame(
212 const QuicConnectionCloseFrame& frame) {
213 return true;
214}
215
QUICHE teama6ef0a62019-03-07 20:34:33 -0500216bool ChloFramerVisitor::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
217 return true;
218}
219
220bool ChloFramerVisitor::OnPathChallengeFrame(
221 const QuicPathChallengeFrame& frame) {
222 return true;
223}
224
225bool ChloFramerVisitor::OnPathResponseFrame(
226 const QuicPathResponseFrame& frame) {
227 return true;
228}
229
230bool ChloFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
231 return true;
232}
233
234bool ChloFramerVisitor::OnWindowUpdateFrame(
235 const QuicWindowUpdateFrame& frame) {
236 return true;
237}
238
239bool ChloFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& frame) {
240 return true;
241}
242
243bool ChloFramerVisitor::OnNewConnectionIdFrame(
244 const QuicNewConnectionIdFrame& frame) {
245 return true;
246}
247
248bool ChloFramerVisitor::OnRetireConnectionIdFrame(
249 const QuicRetireConnectionIdFrame& frame) {
250 return true;
251}
252
253bool ChloFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& frame) {
254 return true;
255}
256
257bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& frame) {
258 return true;
259}
260
261bool ChloFramerVisitor::OnMessageFrame(const QuicMessageFrame& frame) {
262 return true;
263}
264
265bool ChloFramerVisitor::IsValidStatelessResetToken(QuicUint128 token) const {
266 return false;
267}
268
fkastenholz3c4eabf2019-04-22 07:49:59 -0700269bool ChloFramerVisitor::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500270 return true;
271}
272
fkastenholz3c4eabf2019-04-22 07:49:59 -0700273bool ChloFramerVisitor::OnStreamsBlockedFrame(
274 const QuicStreamsBlockedFrame& frame) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500275 return true;
276}
277
278void ChloFramerVisitor::OnError(CryptoFramer* framer) {}
279
280void ChloFramerVisitor::OnHandshakeMessage(
281 const CryptoHandshakeMessage& message) {
282 if (delegate_ != nullptr) {
283 delegate_->OnChlo(framer_->transport_version(), connection_id_, message);
284 }
285 found_chlo_ = true;
286}
287
288} // namespace
289
290// static
291bool ChloExtractor::Extract(const QuicEncryptedPacket& packet,
292 const ParsedQuicVersionVector& versions,
293 const QuicTagVector& create_session_tag_indicators,
294 Delegate* delegate,
295 uint8_t connection_id_length) {
296 QuicFramer framer(versions, QuicTime::Zero(), Perspective::IS_SERVER,
297 connection_id_length);
298 ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate);
299 framer.set_visitor(&visitor);
300 if (!framer.ProcessPacket(packet)) {
301 return false;
302 }
303 return visitor.found_chlo() || visitor.chlo_contains_tags();
304}
305
306} // namespace quic