Handshake.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 83 SSL-Bump Server/Peer negotiation */
10 
11 #include "squid.h"
12 #include "sbuf/Stream.h"
13 #include "security/Handshake.h"
14 #if USE_OPENSSL
15 #include "ssl/support.h"
16 #endif
17 
18 #include <unordered_set>
19 
20 namespace Security {
21 /*
22  * The types below represent various SSL and TLS protocol elements. Most names
23  * are based on RFC 5264 and RFC 6066 terminology. Objects of these explicit
24  * types are stored or passed around. Other protocol elements are simply parsed
25  * in-place, without declaring a corresponding explicit class.
26  */
27 
31  ctAlert = 21,
34 };
35 
38 {
39 public:
41 
42  uint8_t type;
45 };
46 
49 {
50 public:
52 
54 };
55 
62 };
63 
65 class Handshake
66 {
67 public:
68  explicit Handshake(Parser::BinaryTokenizer &tk);
69 
70  uint8_t msg_type;
72 };
73 
75 class Alert
76 {
77 public:
78  explicit Alert(Parser::BinaryTokenizer &tk);
79 
80  bool fatal() const { return level == 2; }
81 
82  uint8_t level;
83  uint8_t description;
84 };
85 
87 static const uint64_t HelloRandomSize = 32;
88 
90 class Extension
91 {
92 public:
93  typedef uint16_t Type;
94  explicit Extension(Parser::BinaryTokenizer &tk);
95 
98  bool supported() const;
99 
102 };
103 
105 typedef std::unordered_set<Extension::Type> Extensions;
107 
111 ParseProtocolVersionBase(Parser::BinaryTokenizer &tk, const char *contextLabel, const bool beStrict)
112 {
113  Parser::BinaryTokenizerContext context(tk, contextLabel);
114  uint8_t vMajor = tk.uint8(".major");
115  uint8_t vMinor = tk.uint8(".minor");
116 
117  if (vMajor == 0 && vMinor == 2)
119 
120  if (vMajor == 3) {
121  if (vMinor == 0)
123  return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, (vMinor - 1));
124  }
125 
126  /* handle unsupported versions */
127 
128  const uint16_t vRaw = (vMajor << 8) | vMinor;
129  debugs(83, 7, "unsupported: " << asHex(vRaw));
130  if (beStrict)
131  throw TextException(ToSBuf("unsupported TLS version: ", asHex(vRaw)), Here());
132  // else hide unsupported version details from the caller behind PROTO_NONE
133  return AnyP::ProtocolVersion();
134 }
135 
140 {
141  return ParseProtocolVersionBase(tk, ".version", true);
142 }
143 
148 {
149  return ParseProtocolVersionBase(tk, contextLabel, false);
150 }
151 
152 } // namespace Security
153 
155 {
156  Parser::BinaryTokenizerContext context(tk, "TLSPlaintext");
157  type = tk.uint8(".type");
160  // TODO: Must(version.major == 3);
161  fragment = tk.pstring16(".fragment");
162  context.success();
163 }
164 
166 {
167  Parser::BinaryTokenizerContext context(tk, "Handshake");
168  msg_type = tk.uint8(".msg_type");
169  msg_body = tk.pstring24(".msg_body");
170  context.success();
171 }
172 
174 {
175  Parser::BinaryTokenizerContext context(tk, "Alert");
176  level = tk.uint8(".level");
177  description = tk.uint8(".description");
178  context.success();
179 }
180 
182 {
183  Parser::BinaryTokenizerContext context(tk, "Extension");
184  type = tk.uint16(".type");
185  data = tk.pstring16(".data");
186  context.success();
187 }
188 
189 bool
191 {
192  static const Extensions supportedExtensions = SupportedExtensions();
193  return supportedExtensions.find(type) != supportedExtensions.end();
194 }
195 
197 {
198  Parser::BinaryTokenizerContext context(tk, "Sslv2Record");
199  const uint16_t head = tk.uint16(".head");
200  const uint16_t length = head & 0x7FFF;
201  Must((head & 0x8000) && length); // SSLv2 message [without padding]
202  fragment = tk.area(length, ".fragment");
203  context.success();
204 }
205 
207  compressionSupported(false),
208  doHeartBeats(false),
209  tlsTicketsExtension(false),
210  hasTlsTicket(false),
211  tlsStatusRequest(false),
212  unsupportedExtensions(false)
213 {
214 }
215 
216 /* Security::HandshakeParser */
217 
219  details(new TlsDetails),
220  state(atHelloNone),
221  resumingSession(false),
222  messageSource(source),
223  currentContentType(0),
224  done(nullptr),
225  expectingModernRecords(false)
226 {
227 }
228 
229 void
231 {
232  const Sslv2Record record(tkRecords);
233  tkRecords.commit();
234  details->tlsVersion = AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0);
235  parseVersion2HandshakeMessage(record.fragment);
236  state = atHelloReceived;
237  done = "SSLv2";
238 }
239 
242 bool
244 {
245  Parser::BinaryTokenizer tk(raw, true);
246  const uint16_t head = tk.uint16("?v2Hello.msg_head");
247  const uint8_t type = tk.uint8("?v2Hello.msg_type");
248  const uint16_t length = head & 0x7FFF;
249  return (head & 0x8000) && length && type == 1;
250 }
251 
252 void
254 {
255  if (expectingModernRecords)
256  parseModernRecord();
257  else
258  parseVersion2Record();
259 }
260 
262 void
264 {
265  const TLSPlaintext record(tkRecords);
266  tkRecords.commit();
267 
268  details->tlsVersion = record.version;
269 
270  // RFC 5246: length MUST NOT exceed 2^14
271  Must(record.fragment.length() <= (1 << 14));
272  // RFC 5246: MUST NOT send zero-length [non-application] fragments
273  Must(record.fragment.length() || record.type == ContentType::ctApplicationData);
274 
275  if (currentContentType != record.type) {
276  parseMessages();
277  Must(tkMessages.atEnd()); // no currentContentType leftovers
278  fragments = record.fragment;
279  currentContentType = record.type;
280  } else {
281  fragments.append(record.fragment);
282  }
283 
284  if (tkRecords.atEnd() && !done)
285  parseMessages();
286 }
287 
289 void
291 {
292  tkMessages.reset(fragments, false);
293  for (; !tkMessages.atEnd(); tkMessages.commit()) {
294  switch (currentContentType) {
296  parseChangeCipherCpecMessage();
297  continue;
299  parseAlertMessage();
300  continue;
302  parseHandshakeMessage();
303  continue;
305  parseApplicationDataMessage();
306  continue;
307  }
308  skipMessage("unknown ContentType msg [fragment]");
309  }
310 }
311 
312 void
314 {
315  Must(currentContentType == ContentType::ctChangeCipherSpec);
316  // We are currently ignoring Change Cipher Spec Protocol messages.
317  skipMessage("ChangeCipherSpec msg [fragment]");
318 
319  // In TLS v1.2 and earlier, ChangeCipherSpec is sent after Hello (when
320  // tlsSupportedVersion is already known) and indicates session resumption.
321  // In later TLS versions, ChangeCipherSpec may be sent before and after
322  // Hello, but it is unused for session resumption and should be ignored.
323  if (!details->tlsSupportedVersion || Tls1p3orLater(details->tlsSupportedVersion))
324  return;
325 
326  resumingSession = true;
327 
328  // Everything after the ChangeCipherSpec message may be encrypted. Stop.
329  done = "ChangeCipherSpec in v1.2-";
330 }
331 
332 void
334 {
335  Must(currentContentType == ContentType::ctAlert);
336  const Alert alert(tkMessages);
337  debugs(83, (alert.fatal() ? 2:3),
338  "level " << static_cast<int>(alert.level) <<
339  " description " << static_cast<int>(alert.description));
340  if (alert.fatal())
341  done = "fatal Alert";
342  // else ignore the warning (at least for now)
343 }
344 
345 void
347 {
348  Must(currentContentType == ContentType::ctHandshake);
349 
350  const Handshake message(tkMessages);
351 
352  switch (message.msg_type) {
354  Must(state < atHelloReceived);
355  Must(messageSource == fromClient);
357  state = atHelloReceived;
358  done = "ClientHello";
359  return;
361  Must(state < atHelloReceived);
362  Must(messageSource == fromServer);
363  parseServerHelloHandshakeMessage(message.msg_body);
364  state = atHelloReceived;
365  // for TLSv1.3 and later, anything after the server Hello is encrypted
366  if (Tls1p3orLater(details->tlsSupportedVersion))
367  done = "ServerHello in v1.3+";
368  return;
370  Must(state < atHelloDoneReceived);
371  // zero-length
372  state = atHelloDoneReceived;
373  done = "ServerHelloDone";
374  return;
375  }
376  debugs(83, 5, "ignoring " << message.msg_body.length() << "-byte type-" <<
377  static_cast<unsigned int>(message.msg_type) << " handshake message");
378 }
379 
380 void
382 {
383  Must(currentContentType == ContentType::ctApplicationData);
384  skipMessage("app data [fragment]");
385 }
386 
387 void
389 {
390  Parser::BinaryTokenizer tk(raw);
391  Parser::BinaryTokenizerContext hello(tk, "V2ClientHello");
392  Must(tk.uint8(".type") == hskClientHello); // Only client hello supported.
393  details->tlsSupportedVersion = ParseProtocolVersion(tk);
394  const uint16_t ciphersLen = tk.uint16(".cipher_specs.length");
395  const uint16_t sessionIdLen = tk.uint16(".session_id.length");
396  const uint16_t challengeLen = tk.uint16(".challenge.length");
397  parseV23Ciphers(tk.area(ciphersLen, ".cipher_specs.body"));
398  details->sessionId = tk.area(sessionIdLen, ".session_id.body");
399  tk.skip(challengeLen, ".challenge.body");
400  hello.success();
401 }
402 
403 void
405 {
406  Parser::BinaryTokenizer tk(raw);
407  Parser::BinaryTokenizerContext hello(tk, "ClientHello");
408  details->tlsSupportedVersion = ParseProtocolVersion(tk);
409  details->clientRandom = tk.area(HelloRandomSize, ".random");
410  details->sessionId = tk.pstring8(".session_id");
411  parseCiphers(tk.pstring16(".cipher_suites"));
412  details->compressionSupported = parseCompressionMethods(tk.pstring8(".compression_methods"));
413  if (!tk.atEnd()) // extension-free message ends here
414  parseExtensions(tk.pstring16(".extensions"));
415  hello.success();
416 }
417 
418 bool
420 {
421  if (raw.length() == 0)
422  return false;
423  Parser::BinaryTokenizer tk(raw);
424  while (!tk.atEnd()) {
425  // Probably here we should check for DEFLATE(1) compression method
426  // which is the only supported by openSSL subsystem.
427  if (tk.uint8("compression_method") != 0)
428  return true;
429  }
430  return false;
431 }
432 
433 void
435 {
436  Parser::BinaryTokenizer tk(raw);
437  while (!tk.atEnd()) {
438  Extension extension(tk);
439 
440  if (!details->unsupportedExtensions && !extension.supported()) {
441  debugs(83, 5, "first unsupported extension: " << extension.type);
442  details->unsupportedExtensions = true;
443  }
444 
445  switch(extension.type) {
446  case 0: // The SNI extension; RFC 6066, Section 3
447  details->serverName = parseSniExtension(extension.data);
448  break;
449  case 5: // Certificate Status Request; RFC 6066, Section 8
450  details->tlsStatusRequest = true;
451  break;
452  case 15: // The heartBeats, RFC 6520
453  details->doHeartBeats = true;
454  break;
455  case 16: { // Application-Layer Protocol Negotiation Extension, RFC 7301
456  Parser::BinaryTokenizer tkAPN(extension.data);
457  // Store the entire protocol list, including unsupported-by-Squid
458  // values (if any). We have to use all when peeking at the server.
459  details->tlsAppLayerProtoNeg = tkAPN.pstring16("APN");
460  break;
461  }
462  case 35: // SessionTicket TLS Extension; RFC 5077
463  details->tlsTicketsExtension = true;
464  details->hasTlsTicket = !extension.data.isEmpty();
465  break;
466  case 43: // supported_versions extension; RFC 8446
467  parseSupportedVersionsExtension(extension.data);
468  break;
469  default:
470  // other extensions, including those that Squid does not support, do
471  // not require special handling here, but see unsupportedExtensions
472  break;
473  }
474  }
475 }
476 
477 void
479 {
480  details->ciphers.reserve(raw.length() / sizeof(uint16_t));
481  Parser::BinaryTokenizer tk(raw);
482  while (!tk.atEnd()) {
483  const uint16_t cipher = tk.uint16("cipher");
484  details->ciphers.insert(cipher); // including Squid-unsupported ones
485  }
486 }
487 
488 void
490 {
491  Parser::BinaryTokenizer tk(raw);
492  while (!tk.atEnd()) {
493  // RFC 6101 Appendix E, RFC 5246 Appendix E2
494  // Unlike TLS, ciphers in SSLv23 Hellos are 3 bytes long and come in
495  // two versions: v2 and v3. The two versions may co-exist in a single
496  // SSLv23 Hello. Only v3 ciphers have a first byte value of zero.
497  // The ciphers are needed for our peeking/staring code that
498  // does not support SSLv2, so we ignore v2 ciphers.
499  const uint8_t prefix = tk.uint8("prefix");
500  const uint16_t cipher = tk.uint16("cipher");
501  if (prefix == 0)
502  details->ciphers.insert(cipher); // including Squid-unsupported ones
503  }
504 }
505 
507 void
509 {
510  Parser::BinaryTokenizer tk(raw);
511  Parser::BinaryTokenizerContext hello(tk, "ServerHello");
512  details->tlsSupportedVersion = ParseProtocolVersion(tk);
513  tk.skip(HelloRandomSize, ".random");
514  details->sessionId = tk.pstring8(".session_id");
515  // cipherSuite may be unsupported by a peeking Squid
516  details->ciphers.insert(tk.uint16(".cipher_suite"));
517  details->compressionSupported = tk.uint8(".compression_method") != 0; // not null
518  if (!tk.atEnd()) // extensions present
519  parseExtensions(tk.pstring16(".extensions"));
520  hello.success();
521 }
522 
523 // RFC 6066 Section 3: ServerNameList (may be sent by both clients and servers)
524 SBuf
526 {
527  // Servers SHOULD send an empty SNI extension, not an empty ServerNameList!
528  if (extensionData.isEmpty())
529  return SBuf();
530 
531  // SNI MUST NOT contain more than one name of the same name_type but
532  // we ignore violations and simply return the first host name found.
533  Parser::BinaryTokenizer tkList(extensionData);
534  Parser::BinaryTokenizer tkNames(tkList.pstring16("ServerNameList"));
535  while (!tkNames.atEnd()) {
536  Parser::BinaryTokenizerContext serverName(tkNames, "ServerName");
537  const uint8_t nameType = tkNames.uint8(".name_type");
538  const SBuf name = tkNames.pstring16(".name");
539  serverName.success();
540 
541  if (nameType == 0) {
542  debugs(83, 3, "host_name=" << name);
543  return name; // it may be empty
544  }
545  // else we just parsed a new/unsupported NameType which,
546  // according to RFC 6066, MUST begin with a 16-bit length field
547  }
548  return SBuf(); // SNI extension lacks host_name
549 }
550 
552 void
554 {
555  // Upon detecting a quoted RFC MUST violation, this parser immediately
556  // returns, ignoring the entire extension and resulting in Squid relying on
557  // the legacy_version field value or another (valid) supported_versions
558  // extension. The alternative would be to reject the whole handshake as
559  // invalid. Deployment experience will show which alternative is the best.
560 
561  // Please note that several of these MUSTs also imply certain likely
562  // handling of a hypothetical next TLS version (e.g., v1.4).
563 
564  // RFC 8446 Section 4.1.2:
565  // In TLS 1.3, the client indicates its version preferences in the
566  // "supported_versions" extension (Section 4.2.1) and the legacy_version
567  // field MUST be set to 0x0303, which is the version number for TLS 1.2.
568  //
569  // RFC 8446 Section 4.2.1:
570  // A server which negotiates TLS 1.3 MUST respond by sending a
571  // "supported_versions" extension containing the selected version value
572  // (0x0304). It MUST set the ServerHello.legacy_version field to 0x0303
573  // (TLS 1.2).
574  //
575  // Ignore supported_versions senders violating legacy_version MUSTs above:
576  if (details->tlsSupportedVersion != AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, 2))
577  return;
578 
579  AnyP::ProtocolVersion supportedVersionMax;
580  if (messageSource == fromClient) {
581  Parser::BinaryTokenizer tkList(extensionData);
582  Parser::BinaryTokenizer tkVersions(tkList.pstring8("SupportedVersions"));
583  while (!tkVersions.atEnd()) {
584  const auto version = ParseOptionalProtocolVersion(tkVersions, "supported_version");
585  // ignore values unsupported by Squid,represented by a falsy version
586  if (!version)
587  continue;
588  if (!supportedVersionMax || TlsVersionEarlierThan(supportedVersionMax, version))
589  supportedVersionMax = version;
590  }
591 
592  // ignore empty and ignored-values-only supported_versions
593  if (!supportedVersionMax)
594  return;
595 
596  // supportedVersionMax here may be "earlier" than tlsSupportedVersion: A
597  // TLS v1.3 client may try to negotiate a _legacy_ version X with a TLS
598  // v1.3 server by sending supported_versions containing just X.
599  } else {
600  assert(messageSource == fromServer);
601  Parser::BinaryTokenizer tkVersion(extensionData);
602  const auto version = ParseOptionalProtocolVersion(tkVersion, "selected_version");
603  // Ignore values unsupported by Squid. There should not be any until we
604  // start seeing TLS v2+, but they do not affect TLS framing anyway.
605  if (!version)
606  return;
607  // RFC 8446 Section 4.2.1:
608  // A server which negotiates a version of TLS prior to TLS 1.3 [...]
609  // MUST NOT send the "supported_versions" extension.
611  return;
612  supportedVersionMax = version;
613  }
614 
615  // We overwrite Hello-derived legacy_version because the following MUSTs
616  // indicate that it is ignored in the presence of valid supported_versions
617  // as far as the negotiated version is concerned. For simplicity sake, we
618  // may also overwrite previous valid supported_versions extensions (if any).
619  //
620  // RFC 8446 Section 4.2.1:
621  // If this extension is present in the ClientHello, servers MUST NOT use the
622  // ClientHello.legacy_version value for version negotiation and MUST use
623  // only the "supported_versions" extension to determine client preferences.
624  // Servers MUST only select a version of TLS present in that extension
625  debugs(83, 7, "found " << supportedVersionMax);
626  assert(supportedVersionMax);
627  details->tlsSupportedVersion = supportedVersionMax;
628 }
629 
630 void
632 {
633  // tkMessages/fragments can only contain messages of the same ContentType.
634  // To skip a message, we can and should skip everything we have [left]. If
635  // we have partial messages, debugging will mislead about their boundaries.
636  tkMessages.skip(tkMessages.leftovers().length(), description);
637 }
638 
639 bool
641 {
642  try {
643  if (!expectingModernRecords.configured())
644  expectingModernRecords.configure(!isSslv2Record(data));
645 
646  // data contains everything read so far, but we may read more later
647  tkRecords.reinput(data, true);
648  tkRecords.rollback();
649  while (!done)
650  parseRecord();
651  debugs(83, 7, "success; got: " << done);
652  // we are done; tkRecords may have leftovers we are not interested in
653  return true;
654  }
656  debugs(83, 5, "need more data");
657  return false;
658  }
659  return false; // unreached
660 }
661 
663 static
666 {
667 #if USE_OPENSSL
668 
669  // optimize lookup speed by reserving the number of values x3, approximately
670  Security::Extensions extensions(64);
671 
672  // Keep this list ordered and up to date by running something like
673  // egrep '# *define TLSEXT_TYPE_' /usr/include/openssl/tls1.h
674  // TODO: Teach OpenSSL to return the list of extensions it supports.
675 #if defined(TLSEXT_TYPE_server_name) // 0
676  extensions.insert(TLSEXT_TYPE_server_name);
677 #endif
678 #if defined(TLSEXT_TYPE_max_fragment_length) // 1
679  extensions.insert(TLSEXT_TYPE_max_fragment_length);
680 #endif
681 #if defined(TLSEXT_TYPE_client_certificate_url) // 2
682  extensions.insert(TLSEXT_TYPE_client_certificate_url);
683 #endif
684 #if defined(TLSEXT_TYPE_trusted_ca_keys) // 3
685  extensions.insert(TLSEXT_TYPE_trusted_ca_keys);
686 #endif
687 #if defined(TLSEXT_TYPE_truncated_hmac) // 4
688  extensions.insert(TLSEXT_TYPE_truncated_hmac);
689 #endif
690 #if defined(TLSEXT_TYPE_status_request) // 5
691  extensions.insert(TLSEXT_TYPE_status_request);
692 #endif
693 #if defined(TLSEXT_TYPE_user_mapping) // 6
694  extensions.insert(TLSEXT_TYPE_user_mapping);
695 #endif
696 #if defined(TLSEXT_TYPE_client_authz) // 7
697  extensions.insert(TLSEXT_TYPE_client_authz);
698 #endif
699 #if defined(TLSEXT_TYPE_server_authz) // 8
700  extensions.insert(TLSEXT_TYPE_server_authz);
701 #endif
702 #if defined(TLSEXT_TYPE_cert_type) // 9
703  extensions.insert(TLSEXT_TYPE_cert_type);
704 #endif
705 #if defined(TLSEXT_TYPE_elliptic_curves) // 10
706  extensions.insert(TLSEXT_TYPE_elliptic_curves);
707 #endif
708 #if defined(TLSEXT_TYPE_ec_point_formats) // 11
709  extensions.insert(TLSEXT_TYPE_ec_point_formats);
710 #endif
711 #if defined(TLSEXT_TYPE_srp) // 12
712  extensions.insert(TLSEXT_TYPE_srp);
713 #endif
714 #if defined(TLSEXT_TYPE_signature_algorithms) // 13
715  extensions.insert(TLSEXT_TYPE_signature_algorithms);
716 #endif
717 #if defined(TLSEXT_TYPE_use_srtp) // 14
718  extensions.insert(TLSEXT_TYPE_use_srtp);
719 #endif
720 #if defined(TLSEXT_TYPE_heartbeat) // 15
721  extensions.insert(TLSEXT_TYPE_heartbeat);
722 #endif
723 #if defined(TLSEXT_TYPE_session_ticket) // 35
724  extensions.insert(TLSEXT_TYPE_session_ticket);
725 #endif
726 #if defined(TLSEXT_TYPE_renegotiate) // 0xff01
727  extensions.insert(TLSEXT_TYPE_renegotiate);
728 #endif
729 #if defined(TLSEXT_TYPE_next_proto_neg) // 13172
730  extensions.insert(TLSEXT_TYPE_next_proto_neg);
731 #endif
732 #if defined(TLSEXT_TYPE_supported_versions) // 43
733  extensions.insert(TLSEXT_TYPE_supported_versions);
734 #endif
735 
736  /*
737  * OpenSSL does not support these last extensions by default, but those
738  * building the OpenSSL libraries and/or Squid might define them.
739  */
740 
741  // OpenSSL may be built to support draft-rescorla-tls-opaque-prf-input-00,
742  // with the extension type value configured at build time. OpenSSL, Squid,
743  // and TLS agents must all be built with the same extension type value.
744 #if defined(TLSEXT_TYPE_opaque_prf_input)
745  extensions.insert(TLSEXT_TYPE_opaque_prf_input);
746 #endif
747 
748  // Define this to add extensions supported by your OpenSSL but unknown to
749  // your Squid version. Use {list-initialization} to add multiple extensions.
750 #if defined(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID)
751  extensions.insert(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID);
752 #endif
753 
754  return extensions; // might be empty
755 #else
756 
757  return Extensions(); // no extensions are supported without OpenSSL
758 #endif
759 }
760 
@ ctChangeCipherSpec
Definition: Handshake.cc:30
TLSPlaintext(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:154
AnyP::ProtocolVersion version
Record Layer, not necessarily the negotiated TLS version;.
Definition: Handshake.cc:43
#define Here()
source code location of the caller
Definition: Here.h:15
TLS Alert protocol frame from RFC 5246 Section 7.2.
Definition: Handshake.cc:76
uint8_t level
warning or fatal
Definition: Handshake.cc:82
void parseV23Ciphers(const SBuf &raw)
Definition: Handshake.cc:489
void skipMessage(const char *msgType)
Definition: Handshake.cc:631
@ PROTO_SSL
Definition: ProtocolType.h:41
static AnyP::ProtocolVersion ParseProtocolVersionBase(Parser::BinaryTokenizer &tk, const char *contextLabel, const bool beStrict)
Definition: Handshake.cc:111
AnyP::ProtocolVersion ProtocolVersion()
Protocol version to use in Http::Message structures wrapping FTP messages.
Definition: Elements.cc:24
bool isEmpty() const
Definition: SBuf.h:424
SBuf area(uint64_t size, const char *description)
parse size consecutive bytes as an opaque blob
Definition: SBuf.h:87
TLS Handshake Protocol frame from RFC 5246 Section 7.4.
Definition: Handshake.cc:66
int type
Definition: errorpage.cc:153
SBuf pstring24(const char *description)
up to 16 MiB-long p-string!
void parseVersion2HandshakeMessage(const SBuf &raw)
Definition: Handshake.cc:388
@ hskServerHelloDone
Definition: Handshake.cc:61
HandshakeParser(MessageSource)
Definition: Handshake.cc:218
SBuf msg_body
Handshake Protocol message.
Definition: Handshake.cc:71
HandshakeType
TLS Handshake protocol's handshake types from RFC 5246 Section 7.4.
Definition: Handshake.cc:57
void parseExtensions(const SBuf &raw)
Definition: Handshake.cc:434
@ hskServerHello
Definition: Handshake.cc:59
Handshake(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:165
uint8_t msg_type
see HandshakeType
Definition: Handshake.cc:70
SBuf parseSniExtension(const SBuf &extensionData) const
Definition: Handshake.cc:525
@ hskClientHello
Definition: Handshake.cc:58
void skip(uint64_t size, const char *description)
ignore the next size bytes
TLS Hello Extension from RFC 5246 Section 7.4.1.4.
Definition: Handshake.cc:91
bool TlsVersionEarlierThan(const AnyP::ProtocolVersion &a, const AnyP::ProtocolVersion &b)
whether TLS/SSL protocol a precedes TLS/SSL protocol b
Definition: Handshake.h:140
@ PROTO_TLS
Definition: ProtocolType.h:40
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
uint8_t uint8(const char *description)
parse a single-byte unsigned integer
bool Tls1p2orEarlier(const AnyP::ProtocolVersion &p)
whether the given TLS/SSL protocol is TLS v1.2 or earlier, including SSL
Definition: Handshake.h:153
void success()
reports successful parsing of a named object and calls close()
void parseModernRecord()
parses a single TLS Record Layer frame
Definition: Handshake.cc:263
@ ctApplicationData
Definition: Handshake.cc:33
bool atEnd() const
no more bytes to parse or skip
#define assert(EX)
Definition: assert.h:19
bool parseHello(const SBuf &data)
Definition: Handshake.cc:640
enables efficient debugging with concise field names: Hello.version.major
static int version
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
Definition: Debug.h:277
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:408
bool parseCompressionMethods(const SBuf &raw)
Definition: Handshake.cc:419
static AnyP::ProtocolVersion ParseProtocolVersion(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:139
bool Tls1p3orLater(const AnyP::ProtocolVersion &p)
whether the given TLS/SSL protocol is TLS v1.3 or later
Definition: Handshake.h:160
@ ctHandshake
Definition: Handshake.cc:32
bool supported() const
Definition: Handshake.cc:190
Alert(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:173
void parseSupportedVersionsExtension(const SBuf &extensionData) const
RFC 8446 Section 4.2.1: SupportedVersions extension.
Definition: Handshake.cc:553
ContentType
TLS Record Layer's content types from RFC 5246 Section 6.2.1.
Definition: Handshake.cc:29
static AnyP::ProtocolVersion ParseOptionalProtocolVersion(Parser::BinaryTokenizer &tk, const char *contextLabel)
Definition: Handshake.cc:147
bool fatal() const
Definition: Handshake.cc:80
SBuf fragment
possibly partial content
Definition: Handshake.cc:44
squidaio_request_t * head
Definition: aiops.cc:127
an std::runtime_error with thrower location info
Definition: TextException.h:20
void parseCiphers(const SBuf &raw)
Definition: Handshake.cc:478
TLS Record Layer's frame from RFC 5246 Section 6.2.1.
Definition: Handshake.cc:38
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:73
void parseServerHelloHandshakeMessage(const SBuf &raw)
RFC 5246 Section 7.4.1.3. Server Hello.
Definition: Handshake.cc:508
SBuf pstring8(const char *description)
up to 255 byte-long p-string
std::unordered_set< Extension::Type > Extensions
Extension types optimized for fast lookups.
Definition: Handshake.cc:105
uint16_t uint16(const char *description)
parse a two-byte unsigned integer
@ hskCertificate
Definition: Handshake.cc:60
uint8_t description
close_notify, unexpected_message, etc.
Definition: Handshake.cc:83
Sslv2Record(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:196
static Extensions SupportedExtensions()
A helper function to create a set of all supported TLS extensions.
Definition: Handshake.cc:665
MessageSource
the originator of the TLS handshake being parsed
Definition: Handshake.h:67
static const uint64_t HelloRandomSize
The size of the TLS Random structure from RFC 5246 Section 7.4.1.2.
Definition: Handshake.cc:87
void parseClientHelloHandshakeMessage(const SBuf &raw)
Definition: Handshake.cc:404
void parseMessages()
parses one or more "higher-level protocol" frames of currentContentType
Definition: Handshake.cc:290
Extension(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:181
#define false
Definition: GnuRegex.c:233
Network/connection security abstraction layer.
Definition: Connection.h:34
uint8_t type
see ContentType
Definition: Handshake.cc:42
draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
Definition: Handshake.cc:49
thrown by modern "incremental" parsers when they need more data
Definition: forward.h:18
SBuf pstring16(const char *description)
up to 64 KiB-long p-string
bool isSslv2Record(const SBuf &raw) const
Definition: Handshake.cc:243

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors