2 * Copyright (C) 1996-2021 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 "sbuf/Stream.h"
13 #include "security/Handshake.h"
15 #include "ssl/support.h"
18 #include <unordered_set>
22 * The types below represent various SSL and TLS protocol elements. Most names
23 * are based on RFC 5264 and RFC 6066 terminology. Objects of these explicit
24 * types are stored or passed around. Other protocol elements are simply parsed
25 * in-place, without declaring a corresponding explicit class.
28 /// TLS Record Layer's content types from RFC 5246 Section 6.2.1
30 ctChangeCipherSpec
= 20,
33 ctApplicationData
= 23
36 /// TLS Record Layer's frame from RFC 5246 Section 6.2.1.
40 explicit TLSPlaintext(Parser::BinaryTokenizer
&tk
);
42 uint8_t type
; ///< see ContentType
43 AnyP::ProtocolVersion version
; ///< Record Layer, not necessarily the negotiated TLS version;
44 SBuf fragment
; ///< possibly partial content
47 /// draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
51 explicit Sslv2Record(Parser::BinaryTokenizer
&tk
);
56 /// TLS Handshake protocol's handshake types from RFC 5246 Section 7.4
61 hskServerHelloDone
= 14
64 /// TLS Handshake Protocol frame from RFC 5246 Section 7.4.
68 explicit Handshake(Parser::BinaryTokenizer
&tk
);
70 uint8_t msg_type
; ///< see HandshakeType
71 SBuf msg_body
; ///< Handshake Protocol message
74 /// TLS Alert protocol frame from RFC 5246 Section 7.2.
78 explicit Alert(Parser::BinaryTokenizer
&tk
);
80 bool fatal() const { return level
== 2; }
82 uint8_t level
; ///< warning or fatal
83 uint8_t description
; ///< close_notify, unexpected_message, etc.
86 /// The size of the TLS Random structure from RFC 5246 Section 7.4.1.2.
87 static const uint64_t HelloRandomSize
= 32;
89 /// TLS Hello Extension from RFC 5246 Section 7.4.1.4.
93 typedef uint16_t Type
;
94 explicit Extension(Parser::BinaryTokenizer
&tk
);
96 /// whether this extension is supported by Squid and, hence, may be bumped
97 /// after peeking or spliced after staring (subject to other restrictions)
98 bool supported() const;
104 /// Extension types optimized for fast lookups.
105 typedef std::unordered_set
<Extension::Type
> Extensions
;
106 static Extensions
SupportedExtensions();
108 /// parse TLS ProtocolVersion (uint16) and convert it to AnyP::ProtocolVersion
109 /// \retval PROTO_NONE for unsupported values (in relaxed mode)
110 static AnyP::ProtocolVersion
111 ParseProtocolVersionBase(Parser::BinaryTokenizer
&tk
, const char *contextLabel
, const bool beStrict
)
113 Parser::BinaryTokenizerContext
context(tk
, contextLabel
);
114 uint8_t vMajor
= tk
.uint8(".major");
115 uint8_t vMinor
= tk
.uint8(".minor");
117 if (vMajor
== 0 && vMinor
== 2)
118 return AnyP::ProtocolVersion(AnyP::PROTO_SSL
, 2, 0);
122 return AnyP::ProtocolVersion(AnyP::PROTO_SSL
, 3, 0);
123 return AnyP::ProtocolVersion(AnyP::PROTO_TLS
, 1, (vMinor
- 1));
126 /* handle unsupported versions */
128 const uint16_t vRaw
= (vMajor
<< 8) | vMinor
;
129 debugs(83, 7, "unsupported: " << asHex(vRaw
));
131 throw TextException(ToSBuf("unsupported TLS version: ", asHex(vRaw
)), Here());
132 // else hide unsupported version details from the caller behind PROTO_NONE
133 return AnyP::ProtocolVersion();
136 /// parse a framing-related TLS ProtocolVersion
137 /// \returns a supported SSL or TLS Anyp::ProtocolVersion, never PROTO_NONE
138 static AnyP::ProtocolVersion
139 ParseProtocolVersion(Parser::BinaryTokenizer
&tk
)
141 return ParseProtocolVersionBase(tk
, ".version", true);
144 /// parse a framing-unrelated TLS ProtocolVersion
145 /// \retval PROTO_NONE for unsupported values
146 static AnyP::ProtocolVersion
147 ParseOptionalProtocolVersion(Parser::BinaryTokenizer
&tk
, const char *contextLabel
)
149 return ParseProtocolVersionBase(tk
, contextLabel
, false);
152 } // namespace Security
154 Security::TLSPlaintext::TLSPlaintext(Parser::BinaryTokenizer
&tk
)
156 Parser::BinaryTokenizerContext
context(tk
, "TLSPlaintext");
157 type
= tk
.uint8(".type");
158 Must(type
>= ctChangeCipherSpec
&& type
<= ctApplicationData
);
159 version
= ParseProtocolVersion(tk
);
160 // TODO: Must(version.major == 3);
161 fragment
= tk
.pstring16(".fragment");
165 Security::Handshake::Handshake(Parser::BinaryTokenizer
&tk
)
167 Parser::BinaryTokenizerContext
context(tk
, "Handshake");
168 msg_type
= tk
.uint8(".msg_type");
169 msg_body
= tk
.pstring24(".msg_body");
173 Security::Alert::Alert(Parser::BinaryTokenizer
&tk
)
175 Parser::BinaryTokenizerContext
context(tk
, "Alert");
176 level
= tk
.uint8(".level");
177 description
= tk
.uint8(".description");
181 Security::Extension::Extension(Parser::BinaryTokenizer
&tk
)
183 Parser::BinaryTokenizerContext
context(tk
, "Extension");
184 type
= tk
.uint16(".type");
185 data
= tk
.pstring16(".data");
190 Security::Extension::supported() const
192 static const Extensions supportedExtensions
= SupportedExtensions();
193 return supportedExtensions
.find(type
) != supportedExtensions
.end();
196 Security::Sslv2Record::Sslv2Record(Parser::BinaryTokenizer
&tk
)
198 Parser::BinaryTokenizerContext
context(tk
, "Sslv2Record");
199 const uint16_t head
= tk
.uint16(".head");
200 const uint16_t length
= head
& 0x7FFF;
201 Must((head
& 0x8000) && length
); // SSLv2 message [without padding]
202 fragment
= tk
.area(length
, ".fragment");
206 Security::TlsDetails::TlsDetails():
207 compressionSupported(false),
209 tlsTicketsExtension(false),
211 tlsStatusRequest(false),
212 unsupportedExtensions(false)
216 /* Security::HandshakeParser */
218 Security::HandshakeParser::HandshakeParser(const MessageSource source
):
219 details(new TlsDetails
),
221 resumingSession(false),
222 messageSource(source
),
223 currentContentType(0),
225 expectingModernRecords(false)
230 Security::HandshakeParser::parseVersion2Record()
232 const Sslv2Record
record(tkRecords
);
234 details
->tlsVersion
= AnyP::ProtocolVersion(AnyP::PROTO_SSL
, 2, 0);
235 parseVersion2HandshakeMessage(record
.fragment
);
236 state
= atHelloReceived
;
240 /// RFC 5246. Appendix E.2. Compatibility with SSL 2.0
241 /// And draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
243 Security::HandshakeParser::isSslv2Record(const SBuf
&raw
) const
245 Parser::BinaryTokenizer
tk(raw
, true);
246 const uint16_t head
= tk
.uint16("?v2Hello.msg_head");
247 const uint8_t type
= tk
.uint8("?v2Hello.msg_type");
248 const uint16_t length
= head
& 0x7FFF;
249 return (head
& 0x8000) && length
&& type
== 1;
253 Security::HandshakeParser::parseRecord()
255 if (expectingModernRecords
)
258 parseVersion2Record();
261 /// parses a single TLS Record Layer frame
263 Security::HandshakeParser::parseModernRecord()
265 const TLSPlaintext
record(tkRecords
);
268 details
->tlsVersion
= record
.version
;
270 // RFC 5246: length MUST NOT exceed 2^14
271 Must(record
.fragment
.length() <= (1 << 14));
272 // RFC 5246: MUST NOT send zero-length [non-application] fragments
273 Must(record
.fragment
.length() || record
.type
== ContentType::ctApplicationData
);
275 if (currentContentType
!= record
.type
) {
277 Must(tkMessages
.atEnd()); // no currentContentType leftovers
278 fragments
= record
.fragment
;
279 currentContentType
= record
.type
;
281 fragments
.append(record
.fragment
);
284 if (tkRecords
.atEnd() && !done
)
288 /// parses one or more "higher-level protocol" frames of currentContentType
290 Security::HandshakeParser::parseMessages()
292 tkMessages
.reset(fragments
, false);
293 for (; !tkMessages
.atEnd(); tkMessages
.commit()) {
294 switch (currentContentType
) {
295 case ContentType::ctChangeCipherSpec
:
296 parseChangeCipherCpecMessage();
298 case ContentType::ctAlert
:
301 case ContentType::ctHandshake
:
302 parseHandshakeMessage();
304 case ContentType::ctApplicationData
:
305 parseApplicationDataMessage();
308 skipMessage("unknown ContentType msg [fragment]");
313 Security::HandshakeParser::parseChangeCipherCpecMessage()
315 Must(currentContentType
== ContentType::ctChangeCipherSpec
);
316 // We are currently ignoring Change Cipher Spec Protocol messages.
317 skipMessage("ChangeCipherSpec msg [fragment]");
319 // In TLS v1.2 and earlier, ChangeCipherSpec is sent after Hello (when
320 // tlsSupportedVersion is already known) and indicates session resumption.
321 // In later TLS versions, ChangeCipherSpec may be sent before and after
322 // Hello, but it is unused for session resumption and should be ignored.
323 if (!details
->tlsSupportedVersion
|| Tls1p3orLater(details
->tlsSupportedVersion
))
326 resumingSession
= true;
328 // Everything after the ChangeCipherSpec message may be encrypted. Stop.
329 done
= "ChangeCipherSpec in v1.2-";
333 Security::HandshakeParser::parseAlertMessage()
335 Must(currentContentType
== ContentType::ctAlert
);
336 const Alert
alert(tkMessages
);
337 debugs(83, (alert
.fatal() ? 2:3),
338 "level " << static_cast<int>(alert
.level
) <<
339 " description " << static_cast<int>(alert
.description
));
341 done
= "fatal Alert";
342 // else ignore the warning (at least for now)
346 Security::HandshakeParser::parseHandshakeMessage()
348 Must(currentContentType
== ContentType::ctHandshake
);
350 const Handshake
message(tkMessages
);
352 switch (message
.msg_type
) {
353 case HandshakeType::hskClientHello
:
354 Must(state
< atHelloReceived
);
355 Must(messageSource
== fromClient
);
356 Security::HandshakeParser::parseClientHelloHandshakeMessage(message
.msg_body
);
357 state
= atHelloReceived
;
358 done
= "ClientHello";
360 case HandshakeType::hskServerHello
:
361 Must(state
< atHelloReceived
);
362 Must(messageSource
== fromServer
);
363 parseServerHelloHandshakeMessage(message
.msg_body
);
364 state
= atHelloReceived
;
365 // for TLSv1.3 and later, anything after the server Hello is encrypted
366 if (Tls1p3orLater(details
->tlsSupportedVersion
))
367 done
= "ServerHello in v1.3+";
369 case HandshakeType::hskServerHelloDone
:
370 Must(state
< atHelloDoneReceived
);
372 state
= atHelloDoneReceived
;
373 done
= "ServerHelloDone";
376 debugs(83, 5, "ignoring " << message
.msg_body
.length() << "-byte type-" <<
377 static_cast<unsigned int>(message
.msg_type
) << " handshake message");
381 Security::HandshakeParser::parseApplicationDataMessage()
383 Must(currentContentType
== ContentType::ctApplicationData
);
384 skipMessage("app data [fragment]");
388 Security::HandshakeParser::parseVersion2HandshakeMessage(const SBuf
&raw
)
390 Parser::BinaryTokenizer
tk(raw
);
391 Parser::BinaryTokenizerContext
hello(tk
, "V2ClientHello");
392 Must(tk
.uint8(".type") == hskClientHello
); // Only client hello supported.
393 details
->tlsSupportedVersion
= ParseProtocolVersion(tk
);
394 const uint16_t ciphersLen
= tk
.uint16(".cipher_specs.length");
395 const uint16_t sessionIdLen
= tk
.uint16(".session_id.length");
396 const uint16_t challengeLen
= tk
.uint16(".challenge.length");
397 parseV23Ciphers(tk
.area(ciphersLen
, ".cipher_specs.body"));
398 details
->sessionId
= tk
.area(sessionIdLen
, ".session_id.body");
399 tk
.skip(challengeLen
, ".challenge.body");
404 Security::HandshakeParser::parseClientHelloHandshakeMessage(const SBuf
&raw
)
406 Parser::BinaryTokenizer
tk(raw
);
407 Parser::BinaryTokenizerContext
hello(tk
, "ClientHello");
408 details
->tlsSupportedVersion
= ParseProtocolVersion(tk
);
409 details
->clientRandom
= tk
.area(HelloRandomSize
, ".random");
410 details
->sessionId
= tk
.pstring8(".session_id");
411 parseCiphers(tk
.pstring16(".cipher_suites"));
412 details
->compressionSupported
= parseCompressionMethods(tk
.pstring8(".compression_methods"));
413 if (!tk
.atEnd()) // extension-free message ends here
414 parseExtensions(tk
.pstring16(".extensions"));
419 Security::HandshakeParser::parseCompressionMethods(const SBuf
&raw
)
421 if (raw
.length() == 0)
423 Parser::BinaryTokenizer
tk(raw
);
424 while (!tk
.atEnd()) {
425 // Probably here we should check for DEFLATE(1) compression method
426 // which is the only supported by openSSL subsystem.
427 if (tk
.uint8("compression_method") != 0)
434 Security::HandshakeParser::parseExtensions(const SBuf
&raw
)
436 Parser::BinaryTokenizer
tk(raw
);
437 while (!tk
.atEnd()) {
438 Extension
extension(tk
);
440 if (!details
->unsupportedExtensions
&& !extension
.supported()) {
441 debugs(83, 5, "first unsupported extension: " << extension
.type
);
442 details
->unsupportedExtensions
= true;
445 switch(extension
.type
) {
446 case 0: // The SNI extension; RFC 6066, Section 3
447 details
->serverName
= parseSniExtension(extension
.data
);
449 case 5: // Certificate Status Request; RFC 6066, Section 8
450 details
->tlsStatusRequest
= true;
452 case 15: // The heartBeats, RFC 6520
453 details
->doHeartBeats
= true;
455 case 16: { // Application-Layer Protocol Negotiation Extension, RFC 7301
456 Parser::BinaryTokenizer
tkAPN(extension
.data
);
457 // Store the entire protocol list, including unsupported-by-Squid
458 // values (if any). We have to use all when peeking at the server.
459 details
->tlsAppLayerProtoNeg
= tkAPN
.pstring16("APN");
462 case 35: // SessionTicket TLS Extension; RFC 5077
463 details
->tlsTicketsExtension
= true;
464 details
->hasTlsTicket
= !extension
.data
.isEmpty();
466 case 43: // supported_versions extension; RFC 8446
467 parseSupportedVersionsExtension(extension
.data
);
470 // other extensions, including those that Squid does not support, do
471 // not require special handling here, but see unsupportedExtensions
478 Security::HandshakeParser::parseCiphers(const SBuf
&raw
)
480 details
->ciphers
.reserve(raw
.length() / sizeof(uint16_t));
481 Parser::BinaryTokenizer
tk(raw
);
482 while (!tk
.atEnd()) {
483 const uint16_t cipher
= tk
.uint16("cipher");
484 details
->ciphers
.insert(cipher
); // including Squid-unsupported ones
489 Security::HandshakeParser::parseV23Ciphers(const SBuf
&raw
)
491 Parser::BinaryTokenizer
tk(raw
);
492 while (!tk
.atEnd()) {
493 // RFC 6101 Appendix E, RFC 5246 Appendix E2
494 // Unlike TLS, ciphers in SSLv23 Hellos are 3 bytes long and come in
495 // two versions: v2 and v3. The two versions may co-exist in a single
496 // SSLv23 Hello. Only v3 ciphers have a first byte value of zero.
497 // The ciphers are needed for our peeking/staring code that
498 // does not support SSLv2, so we ignore v2 ciphers.
499 const uint8_t prefix
= tk
.uint8("prefix");
500 const uint16_t cipher
= tk
.uint16("cipher");
502 details
->ciphers
.insert(cipher
); // including Squid-unsupported ones
506 /// RFC 5246 Section 7.4.1.3. Server Hello
508 Security::HandshakeParser::parseServerHelloHandshakeMessage(const SBuf
&raw
)
510 Parser::BinaryTokenizer
tk(raw
);
511 Parser::BinaryTokenizerContext
hello(tk
, "ServerHello");
512 details
->tlsSupportedVersion
= ParseProtocolVersion(tk
);
513 tk
.skip(HelloRandomSize
, ".random");
514 details
->sessionId
= tk
.pstring8(".session_id");
515 // cipherSuite may be unsupported by a peeking Squid
516 details
->ciphers
.insert(tk
.uint16(".cipher_suite"));
517 details
->compressionSupported
= tk
.uint8(".compression_method") != 0; // not null
518 if (!tk
.atEnd()) // extensions present
519 parseExtensions(tk
.pstring16(".extensions"));
523 // RFC 6066 Section 3: ServerNameList (may be sent by both clients and servers)
525 Security::HandshakeParser::parseSniExtension(const SBuf
&extensionData
) const
527 // Servers SHOULD send an empty SNI extension, not an empty ServerNameList!
528 if (extensionData
.isEmpty())
531 // SNI MUST NOT contain more than one name of the same name_type but
532 // we ignore violations and simply return the first host name found.
533 Parser::BinaryTokenizer
tkList(extensionData
);
534 Parser::BinaryTokenizer
tkNames(tkList
.pstring16("ServerNameList"));
535 while (!tkNames
.atEnd()) {
536 Parser::BinaryTokenizerContext
serverName(tkNames
, "ServerName");
537 const uint8_t nameType
= tkNames
.uint8(".name_type");
538 const SBuf name
= tkNames
.pstring16(".name");
539 serverName
.success();
542 debugs(83, 3, "host_name=" << name
);
543 return name
; // it may be empty
545 // else we just parsed a new/unsupported NameType which,
546 // according to RFC 6066, MUST begin with a 16-bit length field
548 return SBuf(); // SNI extension lacks host_name
551 /// RFC 8446 Section 4.2.1: SupportedVersions extension
553 Security::HandshakeParser::parseSupportedVersionsExtension(const SBuf
&extensionData
) const
555 // Upon detecting a quoted RFC MUST violation, this parser immediately
556 // returns, ignoring the entire extension and resulting in Squid relying on
557 // the legacy_version field value or another (valid) supported_versions
558 // extension. The alternative would be to reject the whole handshake as
559 // invalid. Deployment experience will show which alternative is the best.
561 // Please note that several of these MUSTs also imply certain likely
562 // handling of a hypothetical next TLS version (e.g., v1.4).
564 // RFC 8446 Section 4.1.2:
565 // In TLS 1.3, the client indicates its version preferences in the
566 // "supported_versions" extension (Section 4.2.1) and the legacy_version
567 // field MUST be set to 0x0303, which is the version number for TLS 1.2.
569 // RFC 8446 Section 4.2.1:
570 // A server which negotiates TLS 1.3 MUST respond by sending a
571 // "supported_versions" extension containing the selected version value
572 // (0x0304). It MUST set the ServerHello.legacy_version field to 0x0303
575 // Ignore supported_versions senders violating legacy_version MUSTs above:
576 if (details
->tlsSupportedVersion
!= AnyP::ProtocolVersion(AnyP::PROTO_TLS
, 1, 2))
579 AnyP::ProtocolVersion supportedVersionMax
;
580 if (messageSource
== fromClient
) {
581 Parser::BinaryTokenizer
tkList(extensionData
);
582 Parser::BinaryTokenizer
tkVersions(tkList
.pstring8("SupportedVersions"));
583 while (!tkVersions
.atEnd()) {
584 const auto version
= ParseOptionalProtocolVersion(tkVersions
, "supported_version");
585 // ignore values unsupported by Squid,represented by a falsy version
588 if (!supportedVersionMax
|| TlsVersionEarlierThan(supportedVersionMax
, version
))
589 supportedVersionMax
= version
;
592 // ignore empty and ignored-values-only supported_versions
593 if (!supportedVersionMax
)
596 // supportedVersionMax here may be "earlier" than tlsSupportedVersion: A
597 // TLS v1.3 client may try to negotiate a _legacy_ version X with a TLS
598 // v1.3 server by sending supported_versions containing just X.
600 assert(messageSource
== fromServer
);
601 Parser::BinaryTokenizer
tkVersion(extensionData
);
602 const auto version
= ParseOptionalProtocolVersion(tkVersion
, "selected_version");
603 // Ignore values unsupported by Squid. There should not be any until we
604 // start seeing TLS v2+, but they do not affect TLS framing anyway.
607 // RFC 8446 Section 4.2.1:
608 // A server which negotiates a version of TLS prior to TLS 1.3 [...]
609 // MUST NOT send the "supported_versions" extension.
610 if (Tls1p2orEarlier(version
))
612 supportedVersionMax
= version
;
615 // We overwrite Hello-derived legacy_version because the following MUSTs
616 // indicate that it is ignored in the presence of valid supported_versions
617 // as far as the negotiated version is concerned. For simplicity sake, we
618 // may also overwrite previous valid supported_versions extensions (if any).
620 // RFC 8446 Section 4.2.1:
621 // If this extension is present in the ClientHello, servers MUST NOT use the
622 // ClientHello.legacy_version value for version negotiation and MUST use
623 // only the "supported_versions" extension to determine client preferences.
624 // Servers MUST only select a version of TLS present in that extension
625 debugs(83, 7, "found " << supportedVersionMax
);
626 assert(supportedVersionMax
);
627 details
->tlsSupportedVersion
= supportedVersionMax
;
631 Security::HandshakeParser::skipMessage(const char *description
)
633 // tkMessages/fragments can only contain messages of the same ContentType.
634 // To skip a message, we can and should skip everything we have [left]. If
635 // we have partial messages, debugging will mislead about their boundaries.
636 tkMessages
.skip(tkMessages
.leftovers().length(), description
);
640 Security::HandshakeParser::parseHello(const SBuf
&data
)
643 if (!expectingModernRecords
.configured())
644 expectingModernRecords
.configure(!isSslv2Record(data
));
646 // data contains everything read so far, but we may read more later
647 tkRecords
.reinput(data
, true);
648 tkRecords
.rollback();
651 debugs(83, 7, "success; got: " << done
);
652 // we are done; tkRecords may have leftovers we are not interested in
655 catch (const Parser::BinaryTokenizer::InsufficientInput
&) {
656 debugs(83, 5, "need more data");
659 return false; // unreached
662 /// A helper function to create a set of all supported TLS extensions
665 Security::SupportedExtensions()
669 // optimize lookup speed by reserving the number of values x3, approximately
670 Security::Extensions
extensions(64);
672 // Keep this list ordered and up to date by running something like
673 // egrep '# *define TLSEXT_TYPE_' /usr/include/openssl/tls1.h
674 // TODO: Teach OpenSSL to return the list of extensions it supports.
675 #if defined(TLSEXT_TYPE_server_name) // 0
676 extensions
.insert(TLSEXT_TYPE_server_name
);
678 #if defined(TLSEXT_TYPE_max_fragment_length) // 1
679 extensions
.insert(TLSEXT_TYPE_max_fragment_length
);
681 #if defined(TLSEXT_TYPE_client_certificate_url) // 2
682 extensions
.insert(TLSEXT_TYPE_client_certificate_url
);
684 #if defined(TLSEXT_TYPE_trusted_ca_keys) // 3
685 extensions
.insert(TLSEXT_TYPE_trusted_ca_keys
);
687 #if defined(TLSEXT_TYPE_truncated_hmac) // 4
688 extensions
.insert(TLSEXT_TYPE_truncated_hmac
);
690 #if defined(TLSEXT_TYPE_status_request) // 5
691 extensions
.insert(TLSEXT_TYPE_status_request
);
693 #if defined(TLSEXT_TYPE_user_mapping) // 6
694 extensions
.insert(TLSEXT_TYPE_user_mapping
);
696 #if defined(TLSEXT_TYPE_client_authz) // 7
697 extensions
.insert(TLSEXT_TYPE_client_authz
);
699 #if defined(TLSEXT_TYPE_server_authz) // 8
700 extensions
.insert(TLSEXT_TYPE_server_authz
);
702 #if defined(TLSEXT_TYPE_cert_type) // 9
703 extensions
.insert(TLSEXT_TYPE_cert_type
);
705 #if defined(TLSEXT_TYPE_elliptic_curves) // 10
706 extensions
.insert(TLSEXT_TYPE_elliptic_curves
);
708 #if defined(TLSEXT_TYPE_ec_point_formats) // 11
709 extensions
.insert(TLSEXT_TYPE_ec_point_formats
);
711 #if defined(TLSEXT_TYPE_srp) // 12
712 extensions
.insert(TLSEXT_TYPE_srp
);
714 #if defined(TLSEXT_TYPE_signature_algorithms) // 13
715 extensions
.insert(TLSEXT_TYPE_signature_algorithms
);
717 #if defined(TLSEXT_TYPE_use_srtp) // 14
718 extensions
.insert(TLSEXT_TYPE_use_srtp
);
720 #if defined(TLSEXT_TYPE_heartbeat) // 15
721 extensions
.insert(TLSEXT_TYPE_heartbeat
);
723 #if defined(TLSEXT_TYPE_session_ticket) // 35
724 extensions
.insert(TLSEXT_TYPE_session_ticket
);
726 #if defined(TLSEXT_TYPE_renegotiate) // 0xff01
727 extensions
.insert(TLSEXT_TYPE_renegotiate
);
729 #if defined(TLSEXT_TYPE_next_proto_neg) // 13172
730 extensions
.insert(TLSEXT_TYPE_next_proto_neg
);
732 #if defined(TLSEXT_TYPE_supported_versions) // 43
733 extensions
.insert(TLSEXT_TYPE_supported_versions
);
737 * OpenSSL does not support these last extensions by default, but those
738 * building the OpenSSL libraries and/or Squid might define them.
741 // OpenSSL may be built to support draft-rescorla-tls-opaque-prf-input-00,
742 // with the extension type value configured at build time. OpenSSL, Squid,
743 // and TLS agents must all be built with the same extension type value.
744 #if defined(TLSEXT_TYPE_opaque_prf_input)
745 extensions
.insert(TLSEXT_TYPE_opaque_prf_input
);
748 // Define this to add extensions supported by your OpenSSL but unknown to
749 // your Squid version. Use {list-initialization} to add multiple extensions.
750 #if defined(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID)
751 extensions
.insert(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID
);
754 return extensions
; // might be empty
757 return Extensions(); // no extensions are supported without OpenSSL