proxygen
RecordLayer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
10 
11 namespace fizz {
12 
14 
15 static constexpr size_t kHandshakeHeaderSize =
17 
19  folly::IOBufQueue& socketBuf) {
22  if (param) {
23  VLOG(8) << "Received handshake message "
25  return param;
26  }
27  }
28 
29  while (true) {
30  // Read one record. We read one record at a time since records could cause
31  // a change in the record layer.
32  auto message = read(socketBuf);
33  if (!message) {
34  return folly::none;
35  }
36 
39  throw std::runtime_error("spliced handshake data");
40  }
41 
42  switch (message->type) {
43  case ContentType::alert:
44  return Param(decode<Alert>(std::move(message->fragment)));
48  if (param) {
49  VLOG(8) << "Received handshake message "
51  return param;
52  } else {
53  // If we read handshake data but didn't have enough to get a full
54  // message we immediately try to read another record.
55  // TODO: add limits on number of records we buffer
56  continue;
57  }
58  }
60  return Param(AppData(std::move(message->fragment)));
61  default:
62  throw std::runtime_error("unknown content type");
63  }
64  }
65 }
66 
67 template <typename T>
68 static Param parse(Buf handshakeMsg, Buf original) {
69  auto msg = decode<T>(std::move(handshakeMsg));
70  msg.originalEncoding = std::move(original);
71  return std::move(msg);
72 }
73 
74 template <>
75 Param parse<ServerHello>(Buf handshakeMsg, Buf original) {
76  auto shlo = decode<ServerHello>(std::move(handshakeMsg));
77  if (shlo.random == HelloRetryRequest::HrrRandom) {
79  hrr.legacy_version = shlo.legacy_version;
80  hrr.legacy_session_id_echo = std::move(shlo.legacy_session_id_echo);
81  hrr.cipher_suite = shlo.cipher_suite;
82  hrr.legacy_compression_method = shlo.legacy_compression_method;
83  hrr.extensions = std::move(shlo.extensions);
84 
85  hrr.originalEncoding = std::move(original);
86  return std::move(hrr);
87  } else {
88  shlo.originalEncoding = std::move(original);
89  return std::move(shlo);
90  }
91 }
92 
94  folly::IOBufQueue& buf) {
95  folly::io::Cursor cursor(buf.front());
96 
97  if (!cursor.canAdvance(kHandshakeHeaderSize)) {
98  return folly::none;
99  }
100 
101  auto handshakeType =
102  static_cast<HandshakeType>(cursor.readBE<HandshakeTypeType>());
103  auto length = detail::readBits24(cursor);
104 
105  if (length > kMaxHandshakeSize) {
106  throw std::runtime_error("handshake record too big");
107  }
108  if (buf.chainLength() < (cursor - buf.front()) + length) {
109  return folly::none;
110  }
111 
112  Buf handshakeMsg;
113  cursor.clone(handshakeMsg, length);
114  auto original = buf.split(kHandshakeHeaderSize + length);
115 
116  switch (handshakeType) {
118  return parse<ClientHello>(std::move(handshakeMsg), std::move(original));
120  return parse<ServerHello>(std::move(handshakeMsg), std::move(original));
122  return parse<EndOfEarlyData>(
123  std::move(handshakeMsg), std::move(original));
125  return parse<NewSessionTicket>(
126  std::move(handshakeMsg), std::move(original));
128  return parse<EncryptedExtensions>(
129  std::move(handshakeMsg), std::move(original));
131  return parse<CertificateMsg>(
132  std::move(handshakeMsg), std::move(original));
134  return parse<CompressedCertificate>(
135  std::move(handshakeMsg), std::move(original));
137  return parse<CertificateRequest>(
138  std::move(handshakeMsg), std::move(original));
140  return parse<CertificateVerify>(
141  std::move(handshakeMsg), std::move(original));
143  return parse<Finished>(std::move(handshakeMsg), std::move(original));
145  return parse<KeyUpdate>(std::move(handshakeMsg), std::move(original));
146  default:
147  throw std::runtime_error("unknown handshake type");
148  };
149 }
150 
152  return !unparsedHandshakeData_.empty();
153 }
154 } // namespace fizz
std::vector< Extension > extensions
Definition: Types.h:218
std::unique_ptr< folly::IOBuf > split(size_t n)
Definition: IOBufQueue.h:420
Definition: test.c:42
const folly::IOBuf * front() const
Definition: IOBufQueue.h:476
folly::StringPiece toString(StateEnum state)
Definition: State.cpp:16
virtual bool hasUnparsedHandshakeData() const
void append(std::unique_ptr< folly::IOBuf > &&buf, bool pack=false)
Definition: IOBufQueue.cpp:143
size_t chainLength() const
Definition: IOBufQueue.h:492
static constexpr Random HrrRandom
Definition: Types.h:211
boost::variant< ClientHello, ServerHello, EndOfEarlyData, HelloRetryRequest, EncryptedExtensions, CertificateRequest, CompressedCertificate, CertificateMsg, CertificateVerify, Finished, NewSessionTicket, KeyUpdate, Alert, Accept, Connect, AppData, AppWrite, EarlyAppWrite, WriteNewSessionTicket > Param
Definition: Params.h:90
PskType type
bool empty() const
Definition: IOBufQueue.h:503
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Param parse< ServerHello >(Buf handshakeMsg, Buf original)
Definition: RecordLayer.cpp:75
static Param parse(Buf handshakeMsg, Buf original)
Definition: RecordLayer.cpp:68
constexpr size_t kMaxHandshakeSize
Definition: Types.h:78
enum http_parser_type type
Definition: test.c:45
typename std::underlying_type< HandshakeType >::type HandshakeTypeType
Definition: RecordLayer.cpp:13
static constexpr size_t kHandshakeHeaderSize
Definition: RecordLayer.cpp:15
static folly::Optional< Param > decodeHandshakeMessage(folly::IOBufQueue &buf)
Definition: RecordLayer.cpp:93
virtual folly::Optional< Param > readEvent(folly::IOBufQueue &socketBuf)
Definition: RecordLayer.cpp:18
Definition: Actions.h:16
ProtocolVersion legacy_version
Definition: Types.h:210
uint32_t readBits24(folly::io::Cursor &cursor)
Definition: Types-inl.h:210
folly::Optional< Buf > originalEncoding
Definition: Types.h:92
decltype(auto) apply_visitor(Visitor &&visitor, const DiscriminatedPtr< Args... > &variant)
std::unique_ptr< folly::IOBuf > Buf
Definition: Types.h:22
CipherSuite cipher_suite
Definition: Types.h:216
uint8_t legacy_compression_method
Definition: Types.h:217
HandshakeType
Definition: Types.h:62
folly::IOBufQueue unparsedHandshakeData_
Definition: RecordLayer.h:55
static constexpr size_t size
Definition: Types-inl.h:18
virtual folly::Optional< TLSMessage > read(folly::IOBufQueue &buf)=0
constexpr None none
Definition: Optional.h:87