OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/crypto/crypto_framer.h" | 5 #include "net/quic/crypto/crypto_framer.h" |
6 | 6 |
| 7 #include "base/strings/stringprintf.h" |
7 #include "net/quic/crypto/crypto_protocol.h" | 8 #include "net/quic/crypto/crypto_protocol.h" |
8 #include "net/quic/quic_data_reader.h" | 9 #include "net/quic/quic_data_reader.h" |
9 #include "net/quic/quic_data_writer.h" | 10 #include "net/quic/quic_data_writer.h" |
10 | 11 |
11 using base::StringPiece; | 12 using base::StringPiece; |
12 using std::pair; | 13 using std::pair; |
13 using std::vector; | 14 using std::vector; |
14 | 15 |
15 namespace net { | 16 namespace net { |
16 | 17 |
(...skipping 19 matching lines...) Expand all Loading... |
36 CryptoHandshakeMessage* release() { return out_.release(); } | 37 CryptoHandshakeMessage* release() { return out_.release(); } |
37 | 38 |
38 private: | 39 private: |
39 scoped_ptr<CryptoHandshakeMessage> out_; | 40 scoped_ptr<CryptoHandshakeMessage> out_; |
40 bool error_; | 41 bool error_; |
41 }; | 42 }; |
42 | 43 |
43 } // namespace | 44 } // namespace |
44 | 45 |
45 CryptoFramer::CryptoFramer() | 46 CryptoFramer::CryptoFramer() |
46 : visitor_(nullptr), | 47 : visitor_(nullptr), error_detail_(""), num_entries_(0), values_len_(0) { |
47 num_entries_(0), | |
48 values_len_(0) { | |
49 Clear(); | 48 Clear(); |
50 } | 49 } |
51 | 50 |
52 CryptoFramer::~CryptoFramer() {} | 51 CryptoFramer::~CryptoFramer() {} |
53 | 52 |
54 // static | 53 // static |
55 CryptoHandshakeMessage* CryptoFramer::ParseMessage(StringPiece in) { | 54 CryptoHandshakeMessage* CryptoFramer::ParseMessage(StringPiece in) { |
56 OneShotVisitor visitor; | 55 OneShotVisitor visitor; |
57 CryptoFramer framer; | 56 CryptoFramer framer; |
58 | 57 |
59 framer.set_visitor(&visitor); | 58 framer.set_visitor(&visitor); |
60 if (!framer.ProcessInput(in) || visitor.error() || | 59 if (!framer.ProcessInput(in) || visitor.error() || |
61 framer.InputBytesRemaining()) { | 60 framer.InputBytesRemaining()) { |
62 return nullptr; | 61 return nullptr; |
63 } | 62 } |
64 | 63 |
65 return visitor.release(); | 64 return visitor.release(); |
66 } | 65 } |
67 | 66 |
68 bool CryptoFramer::ProcessInput(StringPiece input) { | 67 bool CryptoFramer::ProcessInput(StringPiece input) { |
69 DCHECK_EQ(QUIC_NO_ERROR, error_); | 68 DCHECK_EQ(QUIC_NO_ERROR, error_); |
70 if (error_ != QUIC_NO_ERROR) { | 69 if (error_ != QUIC_NO_ERROR) { |
71 return false; | 70 return false; |
72 } | 71 } |
73 error_ = Process(input); | 72 error_ = Process(input); |
74 if (error_ != QUIC_NO_ERROR) { | 73 if (error_ != QUIC_NO_ERROR) { |
| 74 DCHECK(!error_detail_.empty()); |
75 visitor_->OnError(this); | 75 visitor_->OnError(this); |
76 return false; | 76 return false; |
77 } | 77 } |
78 | 78 |
79 return true; | 79 return true; |
80 } | 80 } |
81 | 81 |
82 // static | 82 // static |
83 QuicData* CryptoFramer::ConstructHandshakeMessage( | 83 QuicData* CryptoFramer::ConstructHandshakeMessage( |
84 const CryptoHandshakeMessage& message) { | 84 const CryptoHandshakeMessage& message) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 } | 180 } |
181 } | 181 } |
182 | 182 |
183 return new QuicData(buffer.release(), len, true); | 183 return new QuicData(buffer.release(), len, true); |
184 } | 184 } |
185 | 185 |
186 void CryptoFramer::Clear() { | 186 void CryptoFramer::Clear() { |
187 message_.Clear(); | 187 message_.Clear(); |
188 tags_and_lengths_.clear(); | 188 tags_and_lengths_.clear(); |
189 error_ = QUIC_NO_ERROR; | 189 error_ = QUIC_NO_ERROR; |
| 190 error_detail_ = ""; |
190 state_ = STATE_READING_TAG; | 191 state_ = STATE_READING_TAG; |
191 } | 192 } |
192 | 193 |
193 QuicErrorCode CryptoFramer::Process(StringPiece input) { | 194 QuicErrorCode CryptoFramer::Process(StringPiece input) { |
194 // Add this data to the buffer. | 195 // Add this data to the buffer. |
195 buffer_.append(input.data(), input.length()); | 196 buffer_.append(input.data(), input.length()); |
196 QuicDataReader reader(buffer_.data(), buffer_.length()); | 197 QuicDataReader reader(buffer_.data(), buffer_.length()); |
197 | 198 |
198 switch (state_) { | 199 switch (state_) { |
199 case STATE_READING_TAG: | 200 case STATE_READING_TAG: |
200 if (reader.BytesRemaining() < kQuicTagSize) { | 201 if (reader.BytesRemaining() < kQuicTagSize) { |
201 break; | 202 break; |
202 } | 203 } |
203 QuicTag message_tag; | 204 QuicTag message_tag; |
204 reader.ReadUInt32(&message_tag); | 205 reader.ReadUInt32(&message_tag); |
205 message_.set_tag(message_tag); | 206 message_.set_tag(message_tag); |
206 state_ = STATE_READING_NUM_ENTRIES; | 207 state_ = STATE_READING_NUM_ENTRIES; |
207 case STATE_READING_NUM_ENTRIES: | 208 case STATE_READING_NUM_ENTRIES: |
208 if (reader.BytesRemaining() < kNumEntriesSize + sizeof(uint16)) { | 209 if (reader.BytesRemaining() < kNumEntriesSize + sizeof(uint16)) { |
209 break; | 210 break; |
210 } | 211 } |
211 reader.ReadUInt16(&num_entries_); | 212 reader.ReadUInt16(&num_entries_); |
212 if (num_entries_ > kMaxEntries) { | 213 if (num_entries_ > kMaxEntries) { |
| 214 error_detail_ = base::StringPrintf("%u entries", num_entries_); |
213 return QUIC_CRYPTO_TOO_MANY_ENTRIES; | 215 return QUIC_CRYPTO_TOO_MANY_ENTRIES; |
214 } | 216 } |
215 uint16 padding; | 217 uint16 padding; |
216 reader.ReadUInt16(&padding); | 218 reader.ReadUInt16(&padding); |
217 | 219 |
218 tags_and_lengths_.reserve(num_entries_); | 220 tags_and_lengths_.reserve(num_entries_); |
219 state_ = STATE_READING_TAGS_AND_LENGTHS; | 221 state_ = STATE_READING_TAGS_AND_LENGTHS; |
220 values_len_ = 0; | 222 values_len_ = 0; |
221 case STATE_READING_TAGS_AND_LENGTHS: { | 223 case STATE_READING_TAGS_AND_LENGTHS: { |
222 if (reader.BytesRemaining() < | 224 if (reader.BytesRemaining() < |
223 num_entries_ * (kQuicTagSize + kCryptoEndOffsetSize)) { | 225 num_entries_ * (kQuicTagSize + kCryptoEndOffsetSize)) { |
224 break; | 226 break; |
225 } | 227 } |
226 | 228 |
227 uint32 last_end_offset = 0; | 229 uint32 last_end_offset = 0; |
228 for (unsigned i = 0; i < num_entries_; ++i) { | 230 for (unsigned i = 0; i < num_entries_; ++i) { |
229 QuicTag tag; | 231 QuicTag tag; |
230 reader.ReadUInt32(&tag); | 232 reader.ReadUInt32(&tag); |
231 if (i > 0 && tag <= tags_and_lengths_[i-1].first) { | 233 if (i > 0 && tag <= tags_and_lengths_[i-1].first) { |
232 if (tag == tags_and_lengths_[i-1].first) { | 234 if (tag == tags_and_lengths_[i-1].first) { |
| 235 error_detail_ = base::StringPrintf("Duplicate tag:%u", tag); |
233 return QUIC_CRYPTO_DUPLICATE_TAG; | 236 return QUIC_CRYPTO_DUPLICATE_TAG; |
234 } | 237 } |
| 238 error_detail_ = base::StringPrintf("Tag %u out of order", tag); |
235 return QUIC_CRYPTO_TAGS_OUT_OF_ORDER; | 239 return QUIC_CRYPTO_TAGS_OUT_OF_ORDER; |
236 } | 240 } |
237 | 241 |
238 uint32 end_offset; | 242 uint32 end_offset; |
239 reader.ReadUInt32(&end_offset); | 243 reader.ReadUInt32(&end_offset); |
240 | 244 |
241 if (end_offset < last_end_offset) { | 245 if (end_offset < last_end_offset) { |
| 246 error_detail_ = base::StringPrintf("End offset: %u vs %u", end_offset, |
| 247 last_end_offset); |
242 return QUIC_CRYPTO_TAGS_OUT_OF_ORDER; | 248 return QUIC_CRYPTO_TAGS_OUT_OF_ORDER; |
243 } | 249 } |
244 tags_and_lengths_.push_back(std::make_pair( | 250 tags_and_lengths_.push_back(std::make_pair( |
245 tag, static_cast<size_t>(end_offset - last_end_offset))); | 251 tag, static_cast<size_t>(end_offset - last_end_offset))); |
246 last_end_offset = end_offset; | 252 last_end_offset = end_offset; |
247 } | 253 } |
248 values_len_ = last_end_offset; | 254 values_len_ = last_end_offset; |
249 state_ = STATE_READING_VALUES; | 255 state_ = STATE_READING_VALUES; |
250 } | 256 } |
251 case STATE_READING_VALUES: | 257 case STATE_READING_VALUES: |
(...skipping 25 matching lines...) Expand all Loading... |
277 } | 283 } |
278 *end_offset += pad_length; | 284 *end_offset += pad_length; |
279 if (!writer->WriteUInt32(*end_offset)) { | 285 if (!writer->WriteUInt32(*end_offset)) { |
280 DCHECK(false) << "Failed to write end offset."; | 286 DCHECK(false) << "Failed to write end offset."; |
281 return false; | 287 return false; |
282 } | 288 } |
283 return true; | 289 return true; |
284 } | 290 } |
285 | 291 |
286 } // namespace net | 292 } // namespace net |
OLD | NEW |