Handshake.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 "security/Handshake.h"
13 #if USE_OPENSSL
14 #include "ssl/support.h"
15 #endif
16 
17 #include <unordered_set>
18 
19 namespace Security {
20 /*
21  * The types below represent various SSL and TLS protocol elements. Most names
22  * are based on RFC 5264 and RFC 6066 terminology. Objects of these explicit
23  * types are stored or passed around. Other protocol elements are simply parsed
24  * in-place, without declaring a corresponding explicit class.
25  */
26 
30  ctAlert = 21,
33 };
34 
37 {
38 public:
40 
41  uint8_t type;
44 };
45 
48 {
49 public:
51 
53 };
54 
61 };
62 
64 class Handshake
65 {
66 public:
67  explicit Handshake(Parser::BinaryTokenizer &tk);
68 
69  uint8_t msg_type;
71 };
72 
74 class Alert
75 {
76 public:
77  explicit Alert(Parser::BinaryTokenizer &tk);
78 
79  bool fatal() const { return level == 2; }
80 
81  uint8_t level;
82  uint8_t description;
83 };
84 
86 static const uint64_t HelloRandomSize = 32;
87 
89 class Extension
90 {
91 public:
92  typedef uint16_t Type;
93  explicit Extension(Parser::BinaryTokenizer &tk);
94 
97  bool supported() const;
98 
101 };
102 
104 typedef std::unordered_set<Extension::Type> Extensions;
106 
107 } // namespace Security
108 
112 {
113  Parser::BinaryTokenizerContext context(tk, ".version");
114  uint8_t vMajor = tk.uint8(".major");
115  uint8_t vMinor = tk.uint8(".minor");
116  if (vMajor == 0 && vMinor == 2)
118 
119  Must(vMajor == 3);
120  if (vMinor == 0)
122 
123  return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, (vMinor - 1));
124 }
125 
127 {
128  Parser::BinaryTokenizerContext context(tk, "TLSPlaintext");
129  type = tk.uint8(".type");
132  // TODO: Must(version.major == 3);
133  fragment = tk.pstring16(".fragment");
134  context.success();
135 }
136 
138 {
139  Parser::BinaryTokenizerContext context(tk, "Handshake");
140  msg_type = tk.uint8(".msg_type");
141  msg_body = tk.pstring24(".msg_body");
142  context.success();
143 }
144 
146 {
147  Parser::BinaryTokenizerContext context(tk, "Alert");
148  level = tk.uint8(".level");
149  description = tk.uint8(".description");
150  context.success();
151 }
152 
154 {
155  Parser::BinaryTokenizerContext context(tk, "Extension");
156  type = tk.uint16(".type");
157  data = tk.pstring16(".data");
158  context.success();
159 }
160 
161 bool
163 {
164  static const Extensions supportedExtensions = SupportedExtensions();
165  return supportedExtensions.find(type) != supportedExtensions.end();
166 }
167 
169 {
170  Parser::BinaryTokenizerContext context(tk, "Sslv2Record");
171  const uint16_t head = tk.uint16(".head");
172  const uint16_t length = head & 0x7FFF;
173  Must((head & 0x8000) && length); // SSLv2 message [without padding]
174  fragment = tk.area(length, ".fragment");
175  context.success();
176 }
177 
179  compressionSupported(false),
180  doHeartBeats(false),
181  tlsTicketsExtension(false),
182  hasTlsTicket(false),
183  tlsStatusRequest(false),
184  unsupportedExtensions(false)
185 {
186 }
187 
188 /* Security::HandshakeParser */
189 
191  details(new TlsDetails),
192  state(atHelloNone),
193  resumingSession(false),
194  currentContentType(0),
195  done(nullptr),
196  expectingModernRecords(false)
197 {
198 }
199 
200 void
202 {
203  const Sslv2Record record(tkRecords);
204  tkRecords.commit();
205  details->tlsVersion = AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0);
206  parseVersion2HandshakeMessage(record.fragment);
207  state = atHelloReceived;
208  done = "SSLv2";
209 }
210 
213 bool
215 {
216  Parser::BinaryTokenizer tk(raw, true);
217  const uint16_t head = tk.uint16("?v2Hello.msg_head");
218  const uint8_t type = tk.uint8("?v2Hello.msg_type");
219  const uint16_t length = head & 0x7FFF;
220  return (head & 0x8000) && length && type == 1;
221 }
222 
223 void
225 {
226  if (expectingModernRecords)
227  parseModernRecord();
228  else
229  parseVersion2Record();
230 }
231 
233 void
235 {
236  const TLSPlaintext record(tkRecords);
237  tkRecords.commit();
238 
239  details->tlsVersion = record.version;
240 
241  // RFC 5246: length MUST NOT exceed 2^14
242  Must(record.fragment.length() <= (1 << 14));
243  // RFC 5246: MUST NOT send zero-length [non-application] fragments
244  Must(record.fragment.length() || record.type == ContentType::ctApplicationData);
245 
246  if (currentContentType != record.type) {
247  Must(tkMessages.atEnd()); // no currentContentType leftovers
248  fragments = record.fragment;
249  tkMessages.reset(fragments, true); // true because more fragments may come
250  currentContentType = record.type;
251  } else {
252  fragments.append(record.fragment);
253  tkMessages.reinput(fragments, true); // true because more fragments may come
254  tkMessages.rollback();
255  }
256  parseMessages();
257 }
258 
260 void
262 {
263  for (; !tkMessages.atEnd(); tkMessages.commit()) {
264  switch (currentContentType) {
266  parseChangeCipherCpecMessage();
267  continue;
269  parseAlertMessage();
270  continue;
272  parseHandshakeMessage();
273  continue;
275  parseApplicationDataMessage();
276  continue;
277  }
278  skipMessage("unknown ContentType msg [fragment]");
279  }
280 }
281 
282 void
284 {
285  Must(currentContentType == ContentType::ctChangeCipherSpec);
286  // We are currently ignoring Change Cipher Spec Protocol messages.
287  skipMessage("ChangeCipherCpec msg [fragment]");
288 
289  // Everything after the ChangeCipherCpec message may be encrypted.
290  // Continuing parsing is pointless. Stop here.
291  resumingSession = true;
292  done = "ChangeCipherCpec";
293 }
294 
295 void
297 {
298  Must(currentContentType == ContentType::ctAlert);
299  const Alert alert(tkMessages);
300  debugs(83, (alert.fatal() ? 2:3),
301  "level " << static_cast<int>(alert.level) <<
302  " description " << static_cast<int>(alert.description));
303  if (alert.fatal())
304  done = "fatal Alert";
305  // else ignore the warning (at least for now)
306 }
307 
308 void
310 {
311  Must(currentContentType == ContentType::ctHandshake);
312 
313  const Handshake message(tkMessages);
314 
315  switch (message.msg_type) {
317  Must(state < atHelloReceived);
319  state = atHelloReceived;
320  done = "ClientHello";
321  return;
323  Must(state < atHelloReceived);
324  parseServerHelloHandshakeMessage(message.msg_body);
325  state = atHelloReceived;
326  return;
328  Must(state < atCertificatesReceived);
329  parseServerCertificates(message.msg_body);
330  state = atCertificatesReceived;
331  return;
333  Must(state < atHelloDoneReceived);
334  // zero-length
335  state = atHelloDoneReceived;
336  done = "ServerHelloDone";
337  return;
338  }
339  debugs(83, 5, "ignoring " << message.msg_body.length() << "-byte type-" <<
340  static_cast<unsigned int>(message.msg_type) << " handshake message");
341 }
342 
343 void
345 {
346  Must(currentContentType == ContentType::ctApplicationData);
347  skipMessage("app data [fragment]");
348 }
349 
350 void
352 {
353  Parser::BinaryTokenizer tk(raw);
354  Parser::BinaryTokenizerContext hello(tk, "V2ClientHello");
355  Must(tk.uint8(".type") == hskClientHello); // Only client hello supported.
356  details->tlsSupportedVersion = ParseProtocolVersion(tk);
357  const uint16_t ciphersLen = tk.uint16(".cipher_specs.length");
358  const uint16_t sessionIdLen = tk.uint16(".session_id.length");
359  const uint16_t challengeLen = tk.uint16(".challenge.length");
360  parseV23Ciphers(tk.area(ciphersLen, ".cipher_specs.body"));
361  details->sessionId = tk.area(sessionIdLen, ".session_id.body");
362  tk.skip(challengeLen, ".challenge.body");
363  hello.success();
364 }
365 
366 void
368 {
369  Parser::BinaryTokenizer tk(raw);
370  Parser::BinaryTokenizerContext hello(tk, "ClientHello");
371  details->tlsSupportedVersion = ParseProtocolVersion(tk);
372  details->clientRandom = tk.area(HelloRandomSize, ".random");
373  details->sessionId = tk.pstring8(".session_id");
374  parseCiphers(tk.pstring16(".cipher_suites"));
375  details->compressionSupported = parseCompressionMethods(tk.pstring8(".compression_methods"));
376  if (!tk.atEnd()) // extension-free message ends here
377  parseExtensions(tk.pstring16(".extensions"));
378  hello.success();
379 }
380 
381 bool
383 {
384  if (raw.length() == 0)
385  return false;
386  Parser::BinaryTokenizer tk(raw);
387  while (!tk.atEnd()) {
388  // Probably here we should check for DEFLATE(1) compression method
389  // which is the only supported by openSSL subsystem.
390  if (tk.uint8("compression_method") != 0)
391  return true;
392  }
393  return false;
394 }
395 
396 void
398 {
399  Parser::BinaryTokenizer tk(raw);
400  while (!tk.atEnd()) {
401  Extension extension(tk);
402 
403  if (!details->unsupportedExtensions && !extension.supported()) {
404  debugs(83, 5, "first unsupported extension: " << extension.type);
405  details->unsupportedExtensions = true;
406  }
407 
408  switch(extension.type) {
409  case 0: // The SNI extension; RFC 6066, Section 3
410  details->serverName = parseSniExtension(extension.data);
411  break;
412  case 5: // Certificate Status Request; RFC 6066, Section 8
413  details->tlsStatusRequest = true;
414  break;
415  case 15: // The heartBeats, RFC 6520
416  details->doHeartBeats = true;
417  break;
418  case 16: { // Application-Layer Protocol Negotiation Extension, RFC 7301
419  Parser::BinaryTokenizer tkAPN(extension.data);
420  details->tlsAppLayerProtoNeg = tkAPN.pstring16("APN");
421  break;
422  }
423  case 35: // SessionTicket TLS Extension; RFC 5077
424  details->tlsTicketsExtension = true;
425  details->hasTlsTicket = !extension.data.isEmpty();
426  case 13172: // Next Protocol Negotiation Extension (expired draft?)
427  default:
428  break;
429  }
430  }
431 }
432 
433 void
435 {
436  details->ciphers.reserve(raw.length() / sizeof(uint16_t));
437  Parser::BinaryTokenizer tk(raw);
438  while (!tk.atEnd()) {
439  const uint16_t cipher = tk.uint16("cipher");
440  details->ciphers.insert(cipher);
441  }
442 }
443 
444 void
446 {
447  Parser::BinaryTokenizer tk(raw);
448  while (!tk.atEnd()) {
449  // RFC 6101 Appendix E, RFC 5246 Appendix E2
450  // Unlike TLS, ciphers in SSLv23 Hellos are 3 bytes long and come in
451  // two versions: v2 and v3. The two versions may co-exist in a single
452  // SSLv23 Hello. Only v3 ciphers have a first byte value of zero.
453  // The ciphers are needed for our peeking/staring code that
454  // does not support SSLv2, so we ignore v2 ciphers.
455  const uint8_t prefix = tk.uint8("prefix");
456  const uint16_t cipher = tk.uint16("cipher");
457  if (prefix == 0)
458  details->ciphers.insert(cipher);
459  }
460 }
461 
463 void
465 {
466  Parser::BinaryTokenizer tk(raw);
467  Parser::BinaryTokenizerContext hello(tk, "ServerHello");
468  details->tlsSupportedVersion = ParseProtocolVersion(tk);
469  tk.skip(HelloRandomSize, ".random");
470  details->sessionId = tk.pstring8(".session_id");
471  details->ciphers.insert(tk.uint16(".cipher_suite"));
472  details->compressionSupported = tk.uint8(".compression_method") != 0; // not null
473  if (!tk.atEnd()) // extensions present
474  parseExtensions(tk.pstring16(".extensions"));
475  hello.success();
476 }
477 
478 // RFC 6066 Section 3: ServerNameList (may be sent by both clients and servers)
479 SBuf
481 {
482  // Servers SHOULD send an empty SNI extension, not an empty ServerNameList!
483  if (extensionData.isEmpty())
484  return SBuf();
485 
486  // SNI MUST NOT contain more than one name of the same name_type but
487  // we ignore violations and simply return the first host name found.
488  Parser::BinaryTokenizer tkList(extensionData);
489  Parser::BinaryTokenizer tkNames(tkList.pstring16("ServerNameList"));
490  while (!tkNames.atEnd()) {
491  Parser::BinaryTokenizerContext serverName(tkNames, "ServerName");
492  const uint8_t nameType = tkNames.uint8(".name_type");
493  const SBuf name = tkNames.pstring16(".name");
494  serverName.success();
495 
496  if (nameType == 0) {
497  debugs(83, 3, "host_name=" << name);
498  return name; // it may be empty
499  }
500  // else we just parsed a new/unsupported NameType which,
501  // according to RFC 6066, MUST begin with a 16-bit length field
502  }
503  return SBuf(); // SNI extension lacks host_name
504 }
505 
506 void
508 {
509  // tkMessages/fragments can only contain messages of the same ContentType.
510  // To skip a message, we can and should skip everything we have [left]. If
511  // we have partial messages, debugging will mislead about their boundaries.
512  tkMessages.skip(tkMessages.leftovers().length(), description);
513 }
514 
515 bool
517 {
518  try {
519  if (!expectingModernRecords.configured())
520  expectingModernRecords.configure(!isSslv2Record(data));
521 
522  // data contains everything read so far, but we may read more later
523  tkRecords.reinput(data, true);
524  tkRecords.rollback();
525  while (!done)
526  parseRecord();
527  debugs(83, 7, "success; got: " << done);
528  // we are done; tkRecords may have leftovers we are not interested in
529  return true;
530  }
532  debugs(83, 5, "need more data");
533  return false;
534  }
535  return false; // unreached
536 }
537 
540 Security::CertPointer
542 {
543  Security::CertPointer pCert;
544 #if USE_OPENSSL
545  auto x509Start = reinterpret_cast<const unsigned char *>(raw.rawContent());
546  auto x509Pos = x509Start;
547  X509 *x509 = d2i_X509(nullptr, &x509Pos, raw.length());
548  pCert.resetWithoutLocking(x509);
549  Must(x509); // successfully parsed
550  Must(x509Pos == x509Start + raw.length()); // no leftovers
551 #else
552  assert(false); // this code should never be reached
553  pCert = Security::CertPointer(nullptr); // avoid warnings about uninitialized pCert; XXX: Fix CertPoint declaration.
554  (void)raw; // avoid warnings about unused method parameter; TODO: Add a SimulateUse() macro.
555 #endif
556  assert(pCert);
557  return pCert;
558 }
559 
560 void
562 {
563 #if USE_OPENSSL
564  Parser::BinaryTokenizer tkList(raw);
565  const SBuf clist = tkList.pstring24("CertificateList");
566  Must(tkList.atEnd()); // no leftovers after all certificates
567 
568  Parser::BinaryTokenizer tkItems(clist);
569  while (!tkItems.atEnd()) {
570  if (Security::CertPointer cert = ParseCertificate(tkItems.pstring24("Certificate")))
571  serverCertificates.push_back(cert);
572  debugs(83, 7, "parsed " << serverCertificates.size() << " certificates so far");
573  }
574 #else
575  debugs(83, 7, "no support for CertificateList parsing; ignoring " << raw.length() << " bytes");
576 #endif
577 }
578 
580 static
583 {
584 #if USE_OPENSSL
585 
586  // optimize lookup speed by reserving the number of values x3, approximately
587  Security::Extensions extensions(64);
588 
589  // Keep this list ordered and up to date by running something like
590  // egrep '# *define TLSEXT_TYPE_' /usr/include/openssl/tls1.h
591  // TODO: Teach OpenSSL to return the list of extensions it supports.
592 #if defined(TLSEXT_TYPE_server_name) // 0
593  extensions.insert(TLSEXT_TYPE_server_name);
594 #endif
595 #if defined(TLSEXT_TYPE_max_fragment_length) // 1
596  extensions.insert(TLSEXT_TYPE_max_fragment_length);
597 #endif
598 #if defined(TLSEXT_TYPE_client_certificate_url) // 2
599  extensions.insert(TLSEXT_TYPE_client_certificate_url);
600 #endif
601 #if defined(TLSEXT_TYPE_trusted_ca_keys) // 3
602  extensions.insert(TLSEXT_TYPE_trusted_ca_keys);
603 #endif
604 #if defined(TLSEXT_TYPE_truncated_hmac) // 4
605  extensions.insert(TLSEXT_TYPE_truncated_hmac);
606 #endif
607 #if defined(TLSEXT_TYPE_status_request) // 5
608  extensions.insert(TLSEXT_TYPE_status_request);
609 #endif
610 #if defined(TLSEXT_TYPE_user_mapping) // 6
611  extensions.insert(TLSEXT_TYPE_user_mapping);
612 #endif
613 #if defined(TLSEXT_TYPE_client_authz) // 7
614  extensions.insert(TLSEXT_TYPE_client_authz);
615 #endif
616 #if defined(TLSEXT_TYPE_server_authz) // 8
617  extensions.insert(TLSEXT_TYPE_server_authz);
618 #endif
619 #if defined(TLSEXT_TYPE_cert_type) // 9
620  extensions.insert(TLSEXT_TYPE_cert_type);
621 #endif
622 #if defined(TLSEXT_TYPE_elliptic_curves) // 10
623  extensions.insert(TLSEXT_TYPE_elliptic_curves);
624 #endif
625 #if defined(TLSEXT_TYPE_ec_point_formats) // 11
626  extensions.insert(TLSEXT_TYPE_ec_point_formats);
627 #endif
628 #if defined(TLSEXT_TYPE_srp) // 12
629  extensions.insert(TLSEXT_TYPE_srp);
630 #endif
631 #if defined(TLSEXT_TYPE_signature_algorithms) // 13
632  extensions.insert(TLSEXT_TYPE_signature_algorithms);
633 #endif
634 #if defined(TLSEXT_TYPE_use_srtp) // 14
635  extensions.insert(TLSEXT_TYPE_use_srtp);
636 #endif
637 #if defined(TLSEXT_TYPE_heartbeat) // 15
638  extensions.insert(TLSEXT_TYPE_heartbeat);
639 #endif
640 #if defined(TLSEXT_TYPE_session_ticket) // 35
641  extensions.insert(TLSEXT_TYPE_session_ticket);
642 #endif
643 #if defined(TLSEXT_TYPE_renegotiate) // 0xff01
644  extensions.insert(TLSEXT_TYPE_renegotiate);
645 #endif
646 #if defined(TLSEXT_TYPE_next_proto_neg) // 13172
647  extensions.insert(TLSEXT_TYPE_next_proto_neg);
648 #endif
649 
650  /*
651  * OpenSSL does not support these last extensions by default, but those
652  * building the OpenSSL libraries and/or Squid might define them.
653  */
654 
655  // OpenSSL may be built to support draft-rescorla-tls-opaque-prf-input-00,
656  // with the extension type value configured at build time. OpenSSL, Squid,
657  // and TLS agents must all be built with the same extension type value.
658 #if defined(TLSEXT_TYPE_opaque_prf_input)
659  extensions.insert(TLSEXT_TYPE_opaque_prf_input);
660 #endif
661 
662  // Define this to add extensions supported by your OpenSSL but unknown to
663  // your Squid version. Use {list-initialization} to add multiple extensions.
664 #if defined(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID)
665  extensions.insert(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID);
666 #endif
667 
668  return extensions; // might be empty
669 #else
670 
671  return Extensions(); // no extensions are supported without OpenSSL
672 #endif
673 }
674 
void parseCiphers(const SBuf &raw)
Definition: Handshake.cc:434
bool supported() const
Definition: Handshake.cc:162
Extension(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:153
#define assert(EX)
Definition: assert.h:17
void skipMessage(const char *msgType)
Definition: Handshake.cc:507
AnyP::ProtocolVersion ProtocolVersion()
Protocol version to use in Http::Message structures wrapping FTP messages.
Definition: Elements.cc:24
uint16_t uint16(const char *description)
parse a two-byte unsigned integer
int type
Definition: errorpage.cc:79
static Extensions SupportedExtensions()
A helper function to create a set of all supported TLS extensions.
Definition: Handshake.cc:582
Definition: SBuf.h:87
bool atEnd() const
no more bytes to parse or skip
static CertPointer ParseCertificate(const SBuf &raw)
Definition: Handshake.cc:541
draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
Definition: Handshake.cc:47
Alert(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:145
void parseMessages()
parses one or more "higher-level protocol" frames of currentContentType
Definition: Handshake.cc:261
std::unordered_set< Extension::Type > Extensions
Extension types optimized for fast lookups.
Definition: Handshake.cc:104
bool isEmpty() const
Definition: SBuf.h:422
ContentType
TLS Record Layer's content types from RFC 5246 Section 6.2.1.
Definition: Handshake.cc:28
uint8_t description
close_notify, unexpected_message, etc.
Definition: Handshake.cc:82
void success()
reports successful parsing of a named object and calls close()
TLS Handshake Protocol frame from RFC 5246 Section 7.4.
Definition: Handshake.cc:64
void const char HLPCB void * data
Definition: stub_helper.cc:16
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:405
SBuf pstring8(const char *description)
up to 255 byte-long p-string
bool isSslv2Record(const SBuf &raw) const
Definition: Handshake.cc:214
Handshake(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:137
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
SBuf area(uint64_t size, const char *description)
parse size consecutive bytes as an opaque blob
SBuf pstring24(const char *description)
up to 16 MiB-long p-string!
void parseModernRecord()
parses a single TLS Record Layer frame
Definition: Handshake.cc:234
bool parseHello(const SBuf &data)
Definition: Handshake.cc:516
Sslv2Record(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:168
SBuf pstring16(const char *description)
up to 64 KiB-long p-string
uint8_t uint8(const char *description)
parse a single-byte unsigned integer
void parseServerCertificates(const SBuf &raw)
Definition: Handshake.cc:561
bool parseCompressionMethods(const SBuf &raw)
Definition: Handshake.cc:382
TLS Alert protocol frame from RFC 5246 Section 7.2.
Definition: Handshake.cc:74
SBuf fragment
possibly partial content
Definition: Handshake.cc:43
bool fatal() const
Definition: Handshake.cc:79
void parseVersion2HandshakeMessage(const SBuf &raw)
Definition: Handshake.cc:351
uint8_t level
warning or fatal
Definition: Handshake.cc:81
static const uint64_t HelloRandomSize
The size of the TLS Random structure from RFC 5246 Section 7.4.1.2.
Definition: Handshake.cc:86
SBuf msg_body
Handshake Protocol message.
Definition: Handshake.cc:70
void skip(uint64_t size, const char *description)
ignore the next size bytes
#define Must(cond)
Definition: TextException.h:89
static AnyP::ProtocolVersion ParseProtocolVersion(Parser::BinaryTokenizer &tk)
Convenience helper: We parse ProtocolVersion but store "int".
Definition: Handshake.cc:111
SBuf parseSniExtension(const SBuf &extensionData) const
Definition: Handshake.cc:480
TLS Record Layer's frame from RFC 5246 Section 6.2.1.
Definition: Handshake.cc:36
HandshakeType
TLS Handshake protocol's handshake types from RFC 5246 Section 7.4.
Definition: Handshake.cc:56
void parseExtensions(const SBuf &raw)
Definition: Handshake.cc:397
void parseClientHelloHandshakeMessage(const SBuf &raw)
Definition: Handshake.cc:367
uint8_t type
see ContentType
Definition: Handshake.cc:41
void parseServerHelloHandshakeMessage(const SBuf &raw)
RFC 5246 Section 7.4.1.3. Server Hello.
Definition: Handshake.cc:464
enables efficient debugging with concise field names: Hello.version.major
AnyP::ProtocolVersion version
Record Layer, not necessarily the negotiated TLS version;.
Definition: Handshake.cc:42
uint8_t msg_type
see HandshakeType
Definition: Handshake.cc:69
const char * rawContent() const
Definition: SBuf.cc:539
squidaio_request_t * head
Definition: aiops.cc:127
TLSPlaintext(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:126
#define false
Definition: GnuRegex.c:233
TLS Hello Extension from RFC 5246 Section 7.4.1.4.
Definition: Handshake.cc:89
void parseV23Ciphers(const SBuf &raw)
Definition: Handshake.cc:445

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors