blob: 355ecd74b72abfb160c355b6f0cf7f214ef00858 [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 {}
38 bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
39 bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
40 void OnDecryptedPacket(EncryptionLevel level) override {}
41 bool OnPacketHeader(const QuicPacketHeader& header) override;
42 void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
43 bool OnStreamFrame(const QuicStreamFrame& frame) override;
44 bool OnCryptoFrame(const QuicCryptoFrame& frame) override;
45 bool OnAckFrameStart(QuicPacketNumber largest_acked,
46 QuicTime::Delta ack_delay_time) override;
47 bool OnAckRange(QuicPacketNumber start, QuicPacketNumber end) override;
48 bool OnAckTimestamp(QuicPacketNumber packet_number,
49 QuicTime timestamp) override;
50 bool OnAckFrameEnd(QuicPacketNumber start) override;
51 bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
52 bool OnPingFrame(const QuicPingFrame& frame) override;
53 bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override;
54 bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override;
55 bool OnApplicationCloseFrame(const QuicApplicationCloseFrame& frame) override;
56 bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override;
57 bool OnRetireConnectionIdFrame(
58 const QuicRetireConnectionIdFrame& frame) override;
59 bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override;
60 bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
61 bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override;
62 bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
63 bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
64 bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override;
65 bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override;
66 bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
67 bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
68 bool OnPaddingFrame(const QuicPaddingFrame& frame) override;
69 bool OnMessageFrame(const QuicMessageFrame& frame) override;
70 void OnPacketComplete() override {}
71 bool IsValidStatelessResetToken(QuicUint128 token) const override;
72 void OnAuthenticatedIetfStatelessResetPacket(
73 const QuicIetfStatelessResetPacket& packet) override {}
74
75 // CryptoFramerVisitorInterface implementation.
76 void OnError(CryptoFramer* framer) override;
77 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
78
79 // Shared implementation between OnStreamFrame and OnCryptoFrame.
80 bool OnHandshakeData(QuicStringPiece data);
81
82 bool found_chlo() { return found_chlo_; }
83 bool chlo_contains_tags() { return chlo_contains_tags_; }
84
85 private:
86 QuicFramer* framer_;
87 const QuicTagVector& create_session_tag_indicators_;
88 ChloExtractor::Delegate* delegate_;
89 bool found_chlo_;
90 bool chlo_contains_tags_;
91 QuicConnectionId connection_id_;
92};
93
94ChloFramerVisitor::ChloFramerVisitor(
95 QuicFramer* framer,
96 const QuicTagVector& create_session_tag_indicators,
97 ChloExtractor::Delegate* delegate)
98 : framer_(framer),
99 create_session_tag_indicators_(create_session_tag_indicators),
100 delegate_(delegate),
101 found_chlo_(false),
102 chlo_contains_tags_(false),
103 connection_id_(EmptyQuicConnectionId()) {}
104
105bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version,
106 PacketHeaderFormat /*form*/) {
107 if (!framer_->IsSupportedVersion(version)) {
108 return false;
109 }
110 framer_->set_version(version);
111 return true;
112}
113
114bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
115 const QuicPacketHeader& header) {
116 connection_id_ = header.destination_connection_id;
117 return true;
118}
119bool ChloFramerVisitor::OnUnauthenticatedHeader(
120 const QuicPacketHeader& header) {
121 return true;
122}
123bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& header) {
124 return true;
125}
126void ChloFramerVisitor::OnCoalescedPacket(const QuicEncryptedPacket& packet) {}
127bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700128 if (QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500129 // CHLO will be sent in CRYPTO frames in v47 and above.
130 return false;
131 }
132 QuicStringPiece data(frame.data_buffer, frame.data_length);
133 if (frame.stream_id ==
134 QuicUtils::GetCryptoStreamId(framer_->transport_version()) &&
135 frame.offset == 0 && QuicTextUtils::StartsWith(data, "CHLO")) {
136 return OnHandshakeData(data);
137 }
138 return true;
139}
140
141bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700142 if (!QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500143 // CHLO will be in stream frames before v47.
144 return false;
145 }
146 QuicStringPiece data(frame.data_buffer, frame.data_length);
147 if (frame.offset == 0 && QuicTextUtils::StartsWith(data, "CHLO")) {
148 return OnHandshakeData(data);
149 }
150 return true;
151}
152
153bool ChloFramerVisitor::OnHandshakeData(QuicStringPiece data) {
154 CryptoFramer crypto_framer;
155 crypto_framer.set_visitor(this);
156 if (!crypto_framer.ProcessInput(data)) {
157 return false;
158 }
159 // Interrogate the crypto framer and see if there are any
160 // intersecting tags between what we saw in the maybe-CHLO and the
161 // indicator set.
162 for (const QuicTag tag : create_session_tag_indicators_) {
163 if (crypto_framer.HasTag(tag)) {
164 chlo_contains_tags_ = true;
165 }
166 }
167 if (chlo_contains_tags_ && delegate_) {
168 // Unfortunately, because this is a partial CHLO,
169 // OnHandshakeMessage was never called, so the ALPN was never
170 // extracted. Fake it up a bit and send it to the delegate so that
171 // the correct dispatch can happen.
172 crypto_framer.ForceHandshake();
173 }
174
175 return true;
176}
177
178bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
179 QuicTime::Delta /*ack_delay_time*/) {
180 return true;
181}
182
183bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/,
184 QuicPacketNumber /*end*/) {
185 return true;
186}
187
188bool ChloFramerVisitor::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
189 QuicTime /*timestamp*/) {
190 return true;
191}
192
193bool ChloFramerVisitor::OnAckFrameEnd(QuicPacketNumber /*start*/) {
194 return true;
195}
196
197bool ChloFramerVisitor::OnStopWaitingFrame(const QuicStopWaitingFrame& frame) {
198 return true;
199}
200
201bool ChloFramerVisitor::OnPingFrame(const QuicPingFrame& frame) {
202 return true;
203}
204
205bool ChloFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
206 return true;
207}
208
209bool ChloFramerVisitor::OnConnectionCloseFrame(
210 const QuicConnectionCloseFrame& frame) {
211 return true;
212}
213
214bool ChloFramerVisitor::OnApplicationCloseFrame(
215 const QuicApplicationCloseFrame& frame) {
216 return true;
217}
218
219bool ChloFramerVisitor::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
220 return true;
221}
222
223bool ChloFramerVisitor::OnPathChallengeFrame(
224 const QuicPathChallengeFrame& frame) {
225 return true;
226}
227
228bool ChloFramerVisitor::OnPathResponseFrame(
229 const QuicPathResponseFrame& frame) {
230 return true;
231}
232
233bool ChloFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
234 return true;
235}
236
237bool ChloFramerVisitor::OnWindowUpdateFrame(
238 const QuicWindowUpdateFrame& frame) {
239 return true;
240}
241
242bool ChloFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& frame) {
243 return true;
244}
245
246bool ChloFramerVisitor::OnNewConnectionIdFrame(
247 const QuicNewConnectionIdFrame& frame) {
248 return true;
249}
250
251bool ChloFramerVisitor::OnRetireConnectionIdFrame(
252 const QuicRetireConnectionIdFrame& frame) {
253 return true;
254}
255
256bool ChloFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& frame) {
257 return true;
258}
259
260bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& frame) {
261 return true;
262}
263
264bool ChloFramerVisitor::OnMessageFrame(const QuicMessageFrame& frame) {
265 return true;
266}
267
268bool ChloFramerVisitor::IsValidStatelessResetToken(QuicUint128 token) const {
269 return false;
270}
271
272bool ChloFramerVisitor::OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) {
273 return true;
274}
275
276bool ChloFramerVisitor::OnStreamIdBlockedFrame(
277 const QuicStreamIdBlockedFrame& frame) {
278 return true;
279}
280
281void ChloFramerVisitor::OnError(CryptoFramer* framer) {}
282
283void ChloFramerVisitor::OnHandshakeMessage(
284 const CryptoHandshakeMessage& message) {
285 if (delegate_ != nullptr) {
286 delegate_->OnChlo(framer_->transport_version(), connection_id_, message);
287 }
288 found_chlo_ = true;
289}
290
291} // namespace
292
293// static
294bool ChloExtractor::Extract(const QuicEncryptedPacket& packet,
295 const ParsedQuicVersionVector& versions,
296 const QuicTagVector& create_session_tag_indicators,
297 Delegate* delegate,
298 uint8_t connection_id_length) {
299 QuicFramer framer(versions, QuicTime::Zero(), Perspective::IS_SERVER,
300 connection_id_length);
301 ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate);
302 framer.set_visitor(&visitor);
303 if (!framer.ProcessPacket(packet)) {
304 return false;
305 }
306 return visitor.found_chlo() || visitor.chlo_contains_tags();
307}
308
309} // namespace quic