2 * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 83 SSL-Bump Server/Peer negotiation */
12 #include "security/Handshake.h"
14 #include "ssl/support.h"
17 #include <unordered_set>
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.
27 /// TLS Record Layer's content types from RFC 5246 Section 6.2.1
29 ctChangeCipherSpec
= 20,
32 ctApplicationData
= 23
35 /// TLS Record Layer's frame from RFC 5246 Section 6.2.1.
39 explicit TLSPlaintext(Parser::BinaryTokenizer
&tk
);
41 uint8_t type
; ///< see ContentType
42 AnyP::ProtocolVersion version
; ///< Record Layer, not necessarily the negotiated TLS version;
43 SBuf fragment
; ///< possibly partial content
46 /// draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
50 explicit Sslv2Record(Parser::BinaryTokenizer
&tk
);
55 /// TLS Handshake protocol's handshake types from RFC 5246 Section 7.4
60 hskServerHelloDone
= 14
63 /// TLS Handshake Protocol frame from RFC 5246 Section 7.4.
67 explicit Handshake(Parser::BinaryTokenizer
&tk
);
69 uint8_t msg_type
; ///< see HandshakeType
70 SBuf msg_body
; ///< Handshake Protocol message
73 /// TLS Alert protocol frame from RFC 5246 Section 7.2.
77 explicit Alert(Parser::BinaryTokenizer
&tk
);
79 bool fatal() const { return level
== 2; }
81 uint8_t level
; ///< warning or fatal
82 uint8_t description
; ///< close_notify, unexpected_message, etc.
85 /// The size of the TLS Random structure from RFC 5246 Section 7.4.1.2.
86 static const uint64_t HelloRandomSize
= 32;
88 /// TLS Hello Extension from RFC 5246 Section 7.4.1.4.
92 typedef uint16_t Type
;
93 explicit Extension(Parser::BinaryTokenizer
&tk
);
95 /// whether this extension is supported by Squid and, hence, may be bumped
96 /// after peeking or spliced after staring (subject to other restrictions)
97 bool supported() const;
103 /// Extension types optimized for fast lookups.
104 typedef std::unordered_set
<Extension::Type
> Extensions
;
105 static Extensions
SupportedExtensions();
107 } // namespace Security
109 /// Convenience helper: We parse ProtocolVersion but store "int".
110 static AnyP::ProtocolVersion
111 ParseProtocolVersion(Parser::BinaryTokenizer
&tk
)
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)
117 return AnyP::ProtocolVersion(AnyP::PROTO_SSL
, 2, 0);
121 return AnyP::ProtocolVersion(AnyP::PROTO_SSL
, 3, 0);
123 return AnyP::ProtocolVersion(AnyP::PROTO_TLS
, 1, (vMinor
- 1));
126 Security::TLSPlaintext::TLSPlaintext(Parser::BinaryTokenizer
&tk
)
128 Parser::BinaryTokenizerContext
context(tk
, "TLSPlaintext");
129 type
= tk
.uint8(".type");
130 Must(type
>= ctChangeCipherSpec
&& type
<= ctApplicationData
);
131 version
= ParseProtocolVersion(tk
);
132 // TODO: Must(version.major == 3);
133 fragment
= tk
.pstring16(".fragment");
137 Security::Handshake::Handshake(Parser::BinaryTokenizer
&tk
)
139 Parser::BinaryTokenizerContext
context(tk
, "Handshake");
140 msg_type
= tk
.uint8(".msg_type");
141 msg_body
= tk
.pstring24(".msg_body");
145 Security::Alert::Alert(Parser::BinaryTokenizer
&tk
)
147 Parser::BinaryTokenizerContext
context(tk
, "Alert");
148 level
= tk
.uint8(".level");
149 description
= tk
.uint8(".description");
153 Security::Extension::Extension(Parser::BinaryTokenizer
&tk
)
155 Parser::BinaryTokenizerContext
context(tk
, "Extension");
156 type
= tk
.uint16(".type");
157 data
= tk
.pstring16(".data");
162 Security::Extension::supported() const
164 static const Extensions supportedExtensions
= SupportedExtensions();
165 return supportedExtensions
.find(type
) != supportedExtensions
.end();
168 Security::Sslv2Record::Sslv2Record(Parser::BinaryTokenizer
&tk
)
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");
178 Security::TlsDetails::TlsDetails():
179 compressionSupported(false),
181 tlsTicketsExtension(false),
183 tlsStatusRequest(false),
184 unsupportedExtensions(false)
188 /* Security::HandshakeParser */
190 Security::HandshakeParser::HandshakeParser():
191 details(new TlsDetails
),
193 resumingSession(false),
194 currentContentType(0),
196 expectingModernRecords(false)
201 Security::HandshakeParser::parseVersion2Record()
203 const Sslv2Record
record(tkRecords
);
205 details
->tlsVersion
= AnyP::ProtocolVersion(AnyP::PROTO_SSL
, 2, 0);
206 parseVersion2HandshakeMessage(record
.fragment
);
207 state
= atHelloReceived
;
211 /// RFC 5246. Appendix E.2. Compatibility with SSL 2.0
212 /// And draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
214 Security::HandshakeParser::isSslv2Record(const SBuf
&raw
) const
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;
224 Security::HandshakeParser::parseRecord()
226 if (expectingModernRecords
)
229 parseVersion2Record();
232 /// parses a single TLS Record Layer frame
234 Security::HandshakeParser::parseModernRecord()
236 const TLSPlaintext
record(tkRecords
);
239 details
->tlsVersion
= record
.version
;
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
);
246 if (currentContentType
!= record
.type
) {
248 Must(tkMessages
.atEnd()); // no currentContentType leftovers
249 fragments
= record
.fragment
;
250 currentContentType
= record
.type
;
252 fragments
.append(record
.fragment
);
255 if (tkRecords
.atEnd() && !done
)
259 /// parses one or more "higher-level protocol" frames of currentContentType
261 Security::HandshakeParser::parseMessages()
263 tkMessages
.reset(fragments
, false);
264 for (; !tkMessages
.atEnd(); tkMessages
.commit()) {
265 switch (currentContentType
) {
266 case ContentType::ctChangeCipherSpec
:
267 parseChangeCipherCpecMessage();
269 case ContentType::ctAlert
:
272 case ContentType::ctHandshake
:
273 parseHandshakeMessage();
275 case ContentType::ctApplicationData
:
276 parseApplicationDataMessage();
279 skipMessage("unknown ContentType msg [fragment]");
284 Security::HandshakeParser::parseChangeCipherCpecMessage()
286 Must(currentContentType
== ContentType::ctChangeCipherSpec
);
287 // We are currently ignoring Change Cipher Spec Protocol messages.
288 skipMessage("ChangeCipherCpec msg [fragment]");
290 // Everything after the ChangeCipherCpec message may be encrypted.
291 // Continuing parsing is pointless. Stop here.
292 resumingSession
= true;
293 done
= "ChangeCipherCpec";
297 Security::HandshakeParser::parseAlertMessage()
299 Must(currentContentType
== ContentType::ctAlert
);
300 const Alert
alert(tkMessages
);
301 debugs(83, (alert
.fatal() ? 2:3),
302 "level " << static_cast<int>(alert
.level
) <<
303 " description " << static_cast<int>(alert
.description
));
305 done
= "fatal Alert";
306 // else ignore the warning (at least for now)
310 Security::HandshakeParser::parseHandshakeMessage()
312 Must(currentContentType
== ContentType::ctHandshake
);
314 const Handshake
message(tkMessages
);
316 switch (message
.msg_type
) {
317 case HandshakeType::hskClientHello
:
318 Must(state
< atHelloReceived
);
319 Security::HandshakeParser::parseClientHelloHandshakeMessage(message
.msg_body
);
320 state
= atHelloReceived
;
321 done
= "ClientHello";
323 case HandshakeType::hskServerHello
:
324 Must(state
< atHelloReceived
);
325 parseServerHelloHandshakeMessage(message
.msg_body
);
326 state
= atHelloReceived
;
328 case HandshakeType::hskCertificate
:
329 Must(state
< atCertificatesReceived
);
330 parseServerCertificates(message
.msg_body
);
331 state
= atCertificatesReceived
;
333 case HandshakeType::hskServerHelloDone
:
334 Must(state
< atHelloDoneReceived
);
336 state
= atHelloDoneReceived
;
337 done
= "ServerHelloDone";
340 debugs(83, 5, "ignoring " << message
.msg_body
.length() << "-byte type-" <<
341 static_cast<unsigned int>(message
.msg_type
) << " handshake message");
345 Security::HandshakeParser::parseApplicationDataMessage()
347 Must(currentContentType
== ContentType::ctApplicationData
);
348 skipMessage("app data [fragment]");
352 Security::HandshakeParser::parseVersion2HandshakeMessage(const SBuf
&raw
)
354 Parser::BinaryTokenizer
tk(raw
);
355 Parser::BinaryTokenizerContext
hello(tk
, "V2ClientHello");
356 Must(tk
.uint8(".type") == hskClientHello
); // Only client hello supported.
357 details
->tlsSupportedVersion
= ParseProtocolVersion(tk
);
358 const uint16_t ciphersLen
= tk
.uint16(".cipher_specs.length");
359 const uint16_t sessionIdLen
= tk
.uint16(".session_id.length");
360 const uint16_t challengeLen
= tk
.uint16(".challenge.length");
361 parseV23Ciphers(tk
.area(ciphersLen
, ".cipher_specs.body"));
362 details
->sessionId
= tk
.area(sessionIdLen
, ".session_id.body");
363 tk
.skip(challengeLen
, ".challenge.body");
368 Security::HandshakeParser::parseClientHelloHandshakeMessage(const SBuf
&raw
)
370 Parser::BinaryTokenizer
tk(raw
);
371 Parser::BinaryTokenizerContext
hello(tk
, "ClientHello");
372 details
->tlsSupportedVersion
= ParseProtocolVersion(tk
);
373 details
->clientRandom
= tk
.area(HelloRandomSize
, ".random");
374 details
->sessionId
= tk
.pstring8(".session_id");
375 parseCiphers(tk
.pstring16(".cipher_suites"));
376 details
->compressionSupported
= parseCompressionMethods(tk
.pstring8(".compression_methods"));
377 if (!tk
.atEnd()) // extension-free message ends here
378 parseExtensions(tk
.pstring16(".extensions"));
383 Security::HandshakeParser::parseCompressionMethods(const SBuf
&raw
)
385 if (raw
.length() == 0)
387 Parser::BinaryTokenizer
tk(raw
);
388 while (!tk
.atEnd()) {
389 // Probably here we should check for DEFLATE(1) compression method
390 // which is the only supported by openSSL subsystem.
391 if (tk
.uint8("compression_method") != 0)
398 Security::HandshakeParser::parseExtensions(const SBuf
&raw
)
400 Parser::BinaryTokenizer
tk(raw
);
401 while (!tk
.atEnd()) {
402 Extension
extension(tk
);
404 if (!details
->unsupportedExtensions
&& !extension
.supported()) {
405 debugs(83, 5, "first unsupported extension: " << extension
.type
);
406 details
->unsupportedExtensions
= true;
409 switch(extension
.type
) {
410 case 0: // The SNI extension; RFC 6066, Section 3
411 details
->serverName
= parseSniExtension(extension
.data
);
413 case 5: // Certificate Status Request; RFC 6066, Section 8
414 details
->tlsStatusRequest
= true;
416 case 15: // The heartBeats, RFC 6520
417 details
->doHeartBeats
= true;
419 case 16: { // Application-Layer Protocol Negotiation Extension, RFC 7301
420 Parser::BinaryTokenizer
tkAPN(extension
.data
);
421 details
->tlsAppLayerProtoNeg
= tkAPN
.pstring16("APN");
424 case 35: // SessionTicket TLS Extension; RFC 5077
425 details
->tlsTicketsExtension
= true;
426 details
->hasTlsTicket
= !extension
.data
.isEmpty();
427 case 13172: // Next Protocol Negotiation Extension (expired draft?)
435 Security::HandshakeParser::parseCiphers(const SBuf
&raw
)
437 details
->ciphers
.reserve(raw
.length() / sizeof(uint16_t));
438 Parser::BinaryTokenizer
tk(raw
);
439 while (!tk
.atEnd()) {
440 const uint16_t cipher
= tk
.uint16("cipher");
441 details
->ciphers
.insert(cipher
);
446 Security::HandshakeParser::parseV23Ciphers(const SBuf
&raw
)
448 Parser::BinaryTokenizer
tk(raw
);
449 while (!tk
.atEnd()) {
450 // RFC 6101 Appendix E, RFC 5246 Appendix E2
451 // Unlike TLS, ciphers in SSLv23 Hellos are 3 bytes long and come in
452 // two versions: v2 and v3. The two versions may co-exist in a single
453 // SSLv23 Hello. Only v3 ciphers have a first byte value of zero.
454 // The ciphers are needed for our peeking/staring code that
455 // does not support SSLv2, so we ignore v2 ciphers.
456 const uint8_t prefix
= tk
.uint8("prefix");
457 const uint16_t cipher
= tk
.uint16("cipher");
459 details
->ciphers
.insert(cipher
);
463 /// RFC 5246 Section 7.4.1.3. Server Hello
465 Security::HandshakeParser::parseServerHelloHandshakeMessage(const SBuf
&raw
)
467 Parser::BinaryTokenizer
tk(raw
);
468 Parser::BinaryTokenizerContext
hello(tk
, "ServerHello");
469 details
->tlsSupportedVersion
= ParseProtocolVersion(tk
);
470 tk
.skip(HelloRandomSize
, ".random");
471 details
->sessionId
= tk
.pstring8(".session_id");
472 details
->ciphers
.insert(tk
.uint16(".cipher_suite"));
473 details
->compressionSupported
= tk
.uint8(".compression_method") != 0; // not null
474 if (!tk
.atEnd()) // extensions present
475 parseExtensions(tk
.pstring16(".extensions"));
479 // RFC 6066 Section 3: ServerNameList (may be sent by both clients and servers)
481 Security::HandshakeParser::parseSniExtension(const SBuf
&extensionData
) const
483 // Servers SHOULD send an empty SNI extension, not an empty ServerNameList!
484 if (extensionData
.isEmpty())
487 // SNI MUST NOT contain more than one name of the same name_type but
488 // we ignore violations and simply return the first host name found.
489 Parser::BinaryTokenizer
tkList(extensionData
);
490 Parser::BinaryTokenizer
tkNames(tkList
.pstring16("ServerNameList"));
491 while (!tkNames
.atEnd()) {
492 Parser::BinaryTokenizerContext
serverName(tkNames
, "ServerName");
493 const uint8_t nameType
= tkNames
.uint8(".name_type");
494 const SBuf name
= tkNames
.pstring16(".name");
495 serverName
.success();
498 debugs(83, 3, "host_name=" << name
);
499 return name
; // it may be empty
501 // else we just parsed a new/unsupported NameType which,
502 // according to RFC 6066, MUST begin with a 16-bit length field
504 return SBuf(); // SNI extension lacks host_name
508 Security::HandshakeParser::skipMessage(const char *description
)
510 // tkMessages/fragments can only contain messages of the same ContentType.
511 // To skip a message, we can and should skip everything we have [left]. If
512 // we have partial messages, debugging will mislead about their boundaries.
513 tkMessages
.skip(tkMessages
.leftovers().length(), description
);
517 Security::HandshakeParser::parseHello(const SBuf
&data
)
520 if (!expectingModernRecords
.configured())
521 expectingModernRecords
.configure(!isSslv2Record(data
));
523 // data contains everything read so far, but we may read more later
524 tkRecords
.reinput(data
, true);
525 tkRecords
.rollback();
528 debugs(83, 7, "success; got: " << done
);
529 // we are done; tkRecords may have leftovers we are not interested in
532 catch (const Parser::BinaryTokenizer::InsufficientInput
&) {
533 debugs(83, 5, "need more data");
536 return false; // unreached
539 /// Creates and returns a certificate by parsing a DER-encoded X509 structure.
540 /// Throws on failures.
541 Security::CertPointer
542 Security::HandshakeParser::ParseCertificate(const SBuf
&raw
)
544 Security::CertPointer pCert
;
546 auto x509Start
= reinterpret_cast<const unsigned char *>(raw
.rawContent());
547 auto x509Pos
= x509Start
;
548 X509
*x509
= d2i_X509(nullptr, &x509Pos
, raw
.length());
549 pCert
.resetWithoutLocking(x509
);
550 Must(x509
); // successfully parsed
551 Must(x509Pos
== x509Start
+ raw
.length()); // no leftovers
553 assert(false); // this code should never be reached
554 pCert
= Security::CertPointer(nullptr); // avoid warnings about uninitialized pCert; XXX: Fix CertPoint declaration.
555 (void)raw
; // avoid warnings about unused method parameter; TODO: Add a SimulateUse() macro.
562 Security::HandshakeParser::parseServerCertificates(const SBuf
&raw
)
565 Parser::BinaryTokenizer
tkList(raw
);
566 const SBuf clist
= tkList
.pstring24("CertificateList");
567 Must(tkList
.atEnd()); // no leftovers after all certificates
569 Parser::BinaryTokenizer
tkItems(clist
);
570 while (!tkItems
.atEnd()) {
571 if (Security::CertPointer cert
= ParseCertificate(tkItems
.pstring24("Certificate")))
572 serverCertificates
.push_back(cert
);
573 debugs(83, 7, "parsed " << serverCertificates
.size() << " certificates so far");
576 debugs(83, 7, "no support for CertificateList parsing; ignoring " << raw
.length() << " bytes");
580 /// A helper function to create a set of all supported TLS extensions
583 Security::SupportedExtensions()
587 // optimize lookup speed by reserving the number of values x3, approximately
588 Security::Extensions
extensions(64);
590 // Keep this list ordered and up to date by running something like
591 // egrep '# *define TLSEXT_TYPE_' /usr/include/openssl/tls1.h
592 // TODO: Teach OpenSSL to return the list of extensions it supports.
593 #if defined(TLSEXT_TYPE_server_name) // 0
594 extensions
.insert(TLSEXT_TYPE_server_name
);
596 #if defined(TLSEXT_TYPE_max_fragment_length) // 1
597 extensions
.insert(TLSEXT_TYPE_max_fragment_length
);
599 #if defined(TLSEXT_TYPE_client_certificate_url) // 2
600 extensions
.insert(TLSEXT_TYPE_client_certificate_url
);
602 #if defined(TLSEXT_TYPE_trusted_ca_keys) // 3
603 extensions
.insert(TLSEXT_TYPE_trusted_ca_keys
);
605 #if defined(TLSEXT_TYPE_truncated_hmac) // 4
606 extensions
.insert(TLSEXT_TYPE_truncated_hmac
);
608 #if defined(TLSEXT_TYPE_status_request) // 5
609 extensions
.insert(TLSEXT_TYPE_status_request
);
611 #if defined(TLSEXT_TYPE_user_mapping) // 6
612 extensions
.insert(TLSEXT_TYPE_user_mapping
);
614 #if defined(TLSEXT_TYPE_client_authz) // 7
615 extensions
.insert(TLSEXT_TYPE_client_authz
);
617 #if defined(TLSEXT_TYPE_server_authz) // 8
618 extensions
.insert(TLSEXT_TYPE_server_authz
);
620 #if defined(TLSEXT_TYPE_cert_type) // 9
621 extensions
.insert(TLSEXT_TYPE_cert_type
);
623 #if defined(TLSEXT_TYPE_elliptic_curves) // 10
624 extensions
.insert(TLSEXT_TYPE_elliptic_curves
);
626 #if defined(TLSEXT_TYPE_ec_point_formats) // 11
627 extensions
.insert(TLSEXT_TYPE_ec_point_formats
);
629 #if defined(TLSEXT_TYPE_srp) // 12
630 extensions
.insert(TLSEXT_TYPE_srp
);
632 #if defined(TLSEXT_TYPE_signature_algorithms) // 13
633 extensions
.insert(TLSEXT_TYPE_signature_algorithms
);
635 #if defined(TLSEXT_TYPE_use_srtp) // 14
636 extensions
.insert(TLSEXT_TYPE_use_srtp
);
638 #if defined(TLSEXT_TYPE_heartbeat) // 15
639 extensions
.insert(TLSEXT_TYPE_heartbeat
);
641 #if defined(TLSEXT_TYPE_session_ticket) // 35
642 extensions
.insert(TLSEXT_TYPE_session_ticket
);
644 #if defined(TLSEXT_TYPE_renegotiate) // 0xff01
645 extensions
.insert(TLSEXT_TYPE_renegotiate
);
647 #if defined(TLSEXT_TYPE_next_proto_neg) // 13172
648 extensions
.insert(TLSEXT_TYPE_next_proto_neg
);
652 * OpenSSL does not support these last extensions by default, but those
653 * building the OpenSSL libraries and/or Squid might define them.
656 // OpenSSL may be built to support draft-rescorla-tls-opaque-prf-input-00,
657 // with the extension type value configured at build time. OpenSSL, Squid,
658 // and TLS agents must all be built with the same extension type value.
659 #if defined(TLSEXT_TYPE_opaque_prf_input)
660 extensions
.insert(TLSEXT_TYPE_opaque_prf_input
);
663 // Define this to add extensions supported by your OpenSSL but unknown to
664 // your Squid version. Use {list-initialization} to add multiple extensions.
665 #if defined(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID)
666 extensions
.insert(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID
);
669 return extensions
; // might be empty
672 return Extensions(); // no extensions are supported without OpenSSL