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

 

Introduction

Documentation

Support

Miscellaneous