Handshake.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2022 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
21namespace 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{
40public:
42
43 uint8_t type;
46};
47
50{
51public:
53
55};
56
63};
64
67{
68public:
70
71 uint8_t msg_type;
73};
74
76class Alert
77{
78public:
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
88static const uint64_t HelloRandomSize = 32;
89
92{
93public:
94 typedef uint16_t Type;
96
99 bool supported() const;
100
103};
104
106typedef std::unordered_set<Extension::Type> Extensions;
108
112ParseProtocolVersionBase(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: " << asHex(vRaw));
131 if (beStrict)
132 throw TextException(ToSBuf("unsupported TLS version: ", 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
190bool
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
230void
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
243bool
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
253void
255{
256 if (expectingModernRecords)
257 parseModernRecord();
258 else
259 parseVersion2Record();
260}
261
263void
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
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
290void
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
313void
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
333void
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
346void
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
381void
383{
384 Must(currentContentType == ContentType::ctApplicationData);
385 skipMessage("app data [fragment]");
386}
387
388void
390{
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
404void
406{
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
419bool
421{
422 if (raw.length() == 0)
423 return false;
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
434void
436{
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
478void
480{
481 details->ciphers.reserve(raw.length() / sizeof(uint16_t));
483 while (!tk.atEnd()) {
484 const uint16_t cipher = tk.uint16("cipher");
485 details->ciphers.insert(cipher); // including Squid-unsupported ones
486 }
487}
488
489void
491{
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
508void
510{
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)
525SBuf
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
553void
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
631void
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
640bool
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
664static
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
#define false
Definition: GnuRegex.c:240
#define Here()
source code location of the caller
Definition: Here.h:15
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
Definition: IoManip.h:81
#define Must(condition)
Definition: TextException.h:71
squidaio_request_t * head
Definition: aiops.cc:126
#define assert(EX)
Definition: assert.h:19
static int version
enables efficient debugging with concise field names: Hello.version.major
void success()
reports successful parsing of a named object and calls close()
SBuf area(uint64_t size, const char *description)
parse size consecutive bytes as an opaque blob
SBuf pstring8(const char *description)
up to 255 byte-long p-string
bool atEnd() const
no more bytes to parse or skip
void skip(uint64_t size, const char *description)
ignore the next size bytes
uint16_t uint16(const char *description)
parse a two-byte unsigned integer
uint8_t uint8(const char *description)
parse a single-byte unsigned integer
SBuf pstring16(const char *description)
up to 64 KiB-long p-string
SBuf pstring24(const char *description)
up to 16 MiB-long p-string!
thrown by modern "incremental" parsers when they need more data
Definition: forward.h:18
Definition: SBuf.h:94
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:415
bool isEmpty() const
Definition: SBuf.h:431
TLS Alert protocol frame from RFC 5246 Section 7.2.
Definition: Handshake.cc:77
Alert(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:174
bool fatal() const
Definition: Handshake.cc:81
uint8_t description
close_notify, unexpected_message, etc.
Definition: Handshake.cc:84
uint8_t level
warning or fatal
Definition: Handshake.cc:83
TLS Hello Extension from RFC 5246 Section 7.4.1.4.
Definition: Handshake.cc:92
bool supported() const
Definition: Handshake.cc:191
Extension(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:182
SBuf parseSniExtension(const SBuf &extensionData) const
Definition: Handshake.cc:526
void parseSupportedVersionsExtension(const SBuf &extensionData) const
RFC 8446 Section 4.2.1: SupportedVersions extension.
Definition: Handshake.cc:554
void parseServerHelloHandshakeMessage(const SBuf &raw)
RFC 5246 Section 7.4.1.3. Server Hello.
Definition: Handshake.cc:509
void parseMessages()
parses one or more "higher-level protocol" frames of currentContentType
Definition: Handshake.cc:291
bool isSslv2Record(const SBuf &raw) const
Definition: Handshake.cc:244
bool parseCompressionMethods(const SBuf &raw)
Definition: Handshake.cc:420
void skipMessage(const char *msgType)
Definition: Handshake.cc:632
void parseModernRecord()
parses a single TLS Record Layer frame
Definition: Handshake.cc:264
HandshakeParser(MessageSource)
Definition: Handshake.cc:219
void parseCiphers(const SBuf &raw)
Definition: Handshake.cc:479
MessageSource
the originator of the TLS handshake being parsed
Definition: Handshake.h:67
void parseClientHelloHandshakeMessage(const SBuf &raw)
Definition: Handshake.cc:405
bool parseHello(const SBuf &data)
Definition: Handshake.cc:641
void parseVersion2HandshakeMessage(const SBuf &raw)
Definition: Handshake.cc:389
void parseV23Ciphers(const SBuf &raw)
Definition: Handshake.cc:490
void parseExtensions(const SBuf &raw)
Definition: Handshake.cc:435
TLS Handshake Protocol frame from RFC 5246 Section 7.4.
Definition: Handshake.cc:67
Handshake(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:166
uint8_t msg_type
see HandshakeType
Definition: Handshake.cc:71
SBuf msg_body
Handshake Protocol message.
Definition: Handshake.cc:72
draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
Definition: Handshake.cc:50
Sslv2Record(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:197
TLS Record Layer's frame from RFC 5246 Section 6.2.1.
Definition: Handshake.cc:39
AnyP::ProtocolVersion version
Record Layer, not necessarily the negotiated TLS version;.
Definition: Handshake.cc:44
TLSPlaintext(Parser::BinaryTokenizer &tk)
Definition: Handshake.cc:155
uint8_t type
see ContentType
Definition: Handshake.cc:43
SBuf fragment
possibly partial content
Definition: Handshake.cc:45
an std::runtime_error with thrower location info
Definition: TextException.h:21
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
int type
Definition: errorpage.cc:152
@ PROTO_TLS
Definition: ProtocolType.h:39
@ PROTO_SSL
Definition: ProtocolType.h:40
AnyP::ProtocolVersion ProtocolVersion()
Protocol version to use in Http::Message structures wrapping FTP messages.
Definition: Elements.cc:24
Network/connection security abstraction layer.
Definition: Connection.h:34
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
HandshakeType
TLS Handshake protocol's handshake types from RFC 5246 Section 7.4.
Definition: Handshake.cc:58
@ hskServerHello
Definition: Handshake.cc:60
@ hskCertificate
Definition: Handshake.cc:61
@ hskServerHelloDone
Definition: Handshake.cc:62
@ hskClientHello
Definition: Handshake.cc:59
static Extensions SupportedExtensions()
A helper function to create a set of all supported TLS extensions.
Definition: Handshake.cc:666
ContentType
TLS Record Layer's content types from RFC 5246 Section 6.2.1.
Definition: Handshake.cc:30
@ ctApplicationData
Definition: Handshake.cc:34
@ ctHandshake
Definition: Handshake.cc:33
@ ctChangeCipherSpec
Definition: Handshake.cc:31
static const uint64_t HelloRandomSize
The size of the TLS Random structure from RFC 5246 Section 7.4.1.2.
Definition: Handshake.cc:88
bool Tls1p2orEarlier(const AnyP::ProtocolVersion &p)
whether the given TLS/SSL protocol is TLS v1.2 or earlier, including SSL
Definition: Handshake.h:153
std::unordered_set< Extension::Type > Extensions
Extension types optimized for fast lookups.
Definition: Handshake.cc:106
static AnyP::ProtocolVersion ParseProtocolVersionBase(Parser::BinaryTokenizer &tk, const char *contextLabel, const bool beStrict)
Definition: Handshake.cc:112
bool TlsVersionEarlierThan(const AnyP::ProtocolVersion &a, const AnyP::ProtocolVersion &b)
whether TLS/SSL protocol a precedes TLS/SSL protocol b
Definition: Handshake.h:140
static AnyP::ProtocolVersion ParseOptionalProtocolVersion(Parser::BinaryTokenizer &tk, const char *contextLabel)
Definition: Handshake.cc:148
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors