Go to the documentation of this file.
19 #include <unordered_set>
115 uint8_t vMajor = tk.
uint8(
".major");
116 uint8_t vMinor = tk.
uint8(
".minor");
118 if (vMajor == 0 && vMinor == 2)
129 const uint16_t vRaw = (vMajor << 8) | vMinor;
169 msg_type = tk.
uint8(
".msg_type");
177 level = tk.
uint8(
".level");
178 description = tk.
uint8(
".description");
194 return supportedExtensions.find(
type) != supportedExtensions.end();
201 const uint16_t length =
head & 0x7FFF;
203 fragment = tk.
area(length,
".fragment");
208 compressionSupported(
false),
210 tlsTicketsExtension(
false),
212 tlsStatusRequest(
false),
213 unsupportedExtensions(
false)
222 resumingSession(
false),
223 messageSource(source),
224 currentContentType(0),
226 expectingModernRecords(
false)
236 parseVersion2HandshakeMessage(record.
fragment);
237 state = atHelloReceived;
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;
256 if (expectingModernRecords)
259 parseVersion2Record();
269 details->tlsVersion = record.
version;
276 if (currentContentType != record.
type) {
278 Must(tkMessages.atEnd());
280 currentContentType = record.
type;
285 if (tkRecords.atEnd() && !done)
293 tkMessages.reset(fragments,
false);
294 for (; !tkMessages.atEnd(); tkMessages.commit()) {
295 switch (currentContentType) {
297 parseChangeCipherCpecMessage();
303 parseHandshakeMessage();
306 parseApplicationDataMessage();
309 skipMessage(
"unknown ContentType msg [fragment]");
318 skipMessage(
"ChangeCipherSpec msg [fragment]");
324 if (!details->tlsSupportedVersion ||
Tls1p3orLater(details->tlsSupportedVersion))
327 resumingSession =
true;
330 done =
"ChangeCipherSpec in v1.2-";
337 const Alert alert(tkMessages);
339 "level " <<
static_cast<int>(alert.
level) <<
340 " description " <<
static_cast<int>(alert.
description));
342 done =
"fatal Alert";
355 Must(state < atHelloReceived);
356 Must(messageSource == fromClient);
358 state = atHelloReceived;
359 done =
"ClientHello";
362 Must(state < atHelloReceived);
363 Must(messageSource == fromServer);
364 parseServerHelloHandshakeMessage(message.
msg_body);
365 state = atHelloReceived;
368 done =
"ServerHello in v1.3+";
371 Must(state < atHelloDoneReceived);
373 state = atHelloDoneReceived;
374 done =
"ServerHelloDone";
378 static_cast<unsigned int>(message.
msg_type) <<
" handshake message");
385 skipMessage(
"app data [fragment]");
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");
411 details->sessionId = tk.
pstring8(
".session_id");
412 parseCiphers(tk.
pstring16(
".cipher_suites"));
413 details->compressionSupported = parseCompressionMethods(tk.
pstring8(
".compression_methods"));
415 parseExtensions(tk.
pstring16(
".extensions"));
425 while (!tk.
atEnd()) {
428 if (tk.
uint8(
"compression_method") != 0)
438 while (!tk.
atEnd()) {
441 if (!details->unsupportedExtensions && !extension.
supported()) {
442 debugs(83, 5,
"first unsupported extension: " << extension.
type);
443 details->unsupportedExtensions =
true;
446 switch(extension.
type) {
448 details->serverName = parseSniExtension(extension.
data);
451 details->tlsStatusRequest =
true;
454 details->doHeartBeats =
true;
460 details->tlsAppLayerProtoNeg = tkAPN.
pstring16(
"APN");
464 details->tlsTicketsExtension =
true;
468 parseSupportedVersionsExtension(extension.
data);
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);
493 while (!tk.
atEnd()) {
500 const uint8_t prefix = tk.
uint8(
"prefix");
501 const uint16_t cipher = tk.
uint16(
"cipher");
503 details->ciphers.insert(cipher);
515 details->sessionId = tk.
pstring8(
".session_id");
517 details->ciphers.insert(tk.
uint16(
".cipher_suite"));
518 details->compressionSupported = tk.
uint8(
".compression_method") != 0;
520 parseExtensions(tk.
pstring16(
".extensions"));
536 while (!tkNames.
atEnd()) {
538 const uint8_t nameType = tkNames.
uint8(
".name_type");
543 debugs(83, 3,
"host_name=" << name);
581 if (messageSource == fromClient) {
584 while (!tkVersions.
atEnd()) {
594 if (!supportedVersionMax)
601 assert(messageSource == fromServer);
626 debugs(83, 7,
"found " << supportedVersionMax);
627 assert(supportedVersionMax);
628 details->tlsSupportedVersion = supportedVersionMax;
637 tkMessages.skip(tkMessages.leftovers().length(), description);
644 if (!expectingModernRecords.configured())
645 expectingModernRecords.configure(!isSslv2Record(data));
648 tkRecords.reinput(data,
true);
649 tkRecords.rollback();
652 debugs(83, 7,
"success; got: " << done);
657 debugs(83, 5,
"need more data");
676 #if defined(TLSEXT_TYPE_server_name) // 0
677 extensions.insert(TLSEXT_TYPE_server_name);
679 #if defined(TLSEXT_TYPE_max_fragment_length) // 1
680 extensions.insert(TLSEXT_TYPE_max_fragment_length);
682 #if defined(TLSEXT_TYPE_client_certificate_url) // 2
683 extensions.insert(TLSEXT_TYPE_client_certificate_url);
685 #if defined(TLSEXT_TYPE_trusted_ca_keys) // 3
686 extensions.insert(TLSEXT_TYPE_trusted_ca_keys);
688 #if defined(TLSEXT_TYPE_truncated_hmac) // 4
689 extensions.insert(TLSEXT_TYPE_truncated_hmac);
691 #if defined(TLSEXT_TYPE_status_request) // 5
692 extensions.insert(TLSEXT_TYPE_status_request);
694 #if defined(TLSEXT_TYPE_user_mapping) // 6
695 extensions.insert(TLSEXT_TYPE_user_mapping);
697 #if defined(TLSEXT_TYPE_client_authz) // 7
698 extensions.insert(TLSEXT_TYPE_client_authz);
700 #if defined(TLSEXT_TYPE_server_authz) // 8
701 extensions.insert(TLSEXT_TYPE_server_authz);
703 #if defined(TLSEXT_TYPE_cert_type) // 9
704 extensions.insert(TLSEXT_TYPE_cert_type);
706 #if defined(TLSEXT_TYPE_elliptic_curves) // 10
707 extensions.insert(TLSEXT_TYPE_elliptic_curves);
709 #if defined(TLSEXT_TYPE_ec_point_formats) // 11
710 extensions.insert(TLSEXT_TYPE_ec_point_formats);
712 #if defined(TLSEXT_TYPE_srp) // 12
713 extensions.insert(TLSEXT_TYPE_srp);
715 #if defined(TLSEXT_TYPE_signature_algorithms) // 13
716 extensions.insert(TLSEXT_TYPE_signature_algorithms);
718 #if defined(TLSEXT_TYPE_use_srtp) // 14
719 extensions.insert(TLSEXT_TYPE_use_srtp);
721 #if defined(TLSEXT_TYPE_heartbeat) // 15
722 extensions.insert(TLSEXT_TYPE_heartbeat);
724 #if defined(TLSEXT_TYPE_session_ticket) // 35
725 extensions.insert(TLSEXT_TYPE_session_ticket);
727 #if defined(TLSEXT_TYPE_renegotiate) // 0xff01
728 extensions.insert(TLSEXT_TYPE_renegotiate);
730 #if defined(TLSEXT_TYPE_next_proto_neg) // 13172
731 extensions.insert(TLSEXT_TYPE_next_proto_neg);
733 #if defined(TLSEXT_TYPE_supported_versions) // 43
734 extensions.insert(TLSEXT_TYPE_supported_versions);
745 #if defined(TLSEXT_TYPE_opaque_prf_input)
746 extensions.insert(TLSEXT_TYPE_opaque_prf_input);
751 #if defined(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID)
752 extensions.insert(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID);
TLSPlaintext(Parser::BinaryTokenizer &tk)
AnyP::ProtocolVersion version
Record Layer, not necessarily the negotiated TLS version;.
#define Here()
source code location of the caller
TLS Alert protocol frame from RFC 5246 Section 7.2.
uint8_t level
warning or fatal
void parseV23Ciphers(const SBuf &raw)
void skipMessage(const char *msgType)
void parseVersion2Record()
static AnyP::ProtocolVersion ParseProtocolVersionBase(Parser::BinaryTokenizer &tk, const char *contextLabel, const bool beStrict)
AnyP::ProtocolVersion ProtocolVersion()
Protocol version to use in Http::Message structures wrapping FTP messages.
SBuf area(uint64_t size, const char *description)
parse size consecutive bytes as an opaque blob
TLS Handshake Protocol frame from RFC 5246 Section 7.4.
SBuf pstring24(const char *description)
up to 16 MiB-long p-string!
void parseVersion2HandshakeMessage(const SBuf &raw)
HandshakeParser(MessageSource)
SBuf msg_body
Handshake Protocol message.
HandshakeType
TLS Handshake protocol's handshake types from RFC 5246 Section 7.4.
void parseExtensions(const SBuf &raw)
Handshake(Parser::BinaryTokenizer &tk)
uint8_t msg_type
see HandshakeType
SBuf parseSniExtension(const SBuf &extensionData) const
void skip(uint64_t size, const char *description)
ignore the next size bytes
TLS Hello Extension from RFC 5246 Section 7.4.1.4.
bool TlsVersionEarlierThan(const AnyP::ProtocolVersion &a, const AnyP::ProtocolVersion &b)
whether TLS/SSL protocol a precedes TLS/SSL protocol b
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
void success()
reports successful parsing of a named object and calls close()
void parseModernRecord()
parses a single TLS Record Layer frame
AsHex< Integer > asHex(const Integer n)
a helper to ease AsHex object creation
bool atEnd() const
no more bytes to parse or skip
bool parseHello(const SBuf &data)
enables efficient debugging with concise field names: Hello.version.major
size_type length() const
Returns the number of bytes stored in SBuf.
bool parseCompressionMethods(const SBuf &raw)
static AnyP::ProtocolVersion ParseProtocolVersion(Parser::BinaryTokenizer &tk)
bool Tls1p3orLater(const AnyP::ProtocolVersion &p)
whether the given TLS/SSL protocol is TLS v1.3 or later
Alert(Parser::BinaryTokenizer &tk)
void parseSupportedVersionsExtension(const SBuf &extensionData) const
RFC 8446 Section 4.2.1: SupportedVersions extension.
ContentType
TLS Record Layer's content types from RFC 5246 Section 6.2.1.
static AnyP::ProtocolVersion ParseOptionalProtocolVersion(Parser::BinaryTokenizer &tk, const char *contextLabel)
SBuf fragment
possibly partial content
squidaio_request_t * head
an std::runtime_error with thrower location info
void parseApplicationDataMessage()
void parseChangeCipherCpecMessage()
void parseCiphers(const SBuf &raw)
TLS Record Layer's frame from RFC 5246 Section 6.2.1.
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
void parseServerHelloHandshakeMessage(const SBuf &raw)
RFC 5246 Section 7.4.1.3. Server Hello.
SBuf pstring8(const char *description)
up to 255 byte-long p-string
void parseHandshakeMessage()
std::unordered_set< Extension::Type > Extensions
Extension types optimized for fast lookups.
uint16_t uint16(const char *description)
parse a two-byte unsigned integer
uint8_t description
close_notify, unexpected_message, etc.
Sslv2Record(Parser::BinaryTokenizer &tk)
static Extensions SupportedExtensions()
A helper function to create a set of all supported TLS extensions.
MessageSource
the originator of the TLS handshake being parsed
static const uint64_t HelloRandomSize
The size of the TLS Random structure from RFC 5246 Section 7.4.1.2.
void parseClientHelloHandshakeMessage(const SBuf &raw)
void parseMessages()
parses one or more "higher-level protocol" frames of currentContentType
Extension(Parser::BinaryTokenizer &tk)
Network/connection security abstraction layer.
uint8_t type
see ContentType
#define debugs(SECTION, LEVEL, CONTENT)
draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
SBuf pstring16(const char *description)
up to 64 KiB-long p-string
bool isSslv2Record(const SBuf &raw) const