]> git.ipfire.org Git - thirdparty/squid.git/blob - src/security/Handshake.cc
Source Format Enforcement (#532)
[thirdparty/squid.git] / src / security / Handshake.cc
1 /*
2 * Copyright (C) 1996-2020 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
27 /// TLS Record Layer's content types from RFC 5246 Section 6.2.1
28 enum ContentType {
29 ctChangeCipherSpec = 20,
30 ctAlert = 21,
31 ctHandshake = 22,
32 ctApplicationData = 23
33 };
34
35 /// TLS Record Layer's frame from RFC 5246 Section 6.2.1.
36 class TLSPlaintext
37 {
38 public:
39 explicit TLSPlaintext(Parser::BinaryTokenizer &tk);
40
41 uint8_t type; ///< see ContentType
42 AnyP::ProtocolVersion version; ///< Record Layer, not necessarily the negotiated TLS version;
43 SBuf fragment; ///< possibly partial content
44 };
45
46 /// draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
47 class Sslv2Record
48 {
49 public:
50 explicit Sslv2Record(Parser::BinaryTokenizer &tk);
51
52 SBuf fragment;
53 };
54
55 /// TLS Handshake protocol's handshake types from RFC 5246 Section 7.4
56 enum HandshakeType {
57 hskClientHello = 1,
58 hskServerHello = 2,
59 hskCertificate = 11,
60 hskServerHelloDone = 14
61 };
62
63 /// TLS Handshake Protocol frame from RFC 5246 Section 7.4.
64 class Handshake
65 {
66 public:
67 explicit Handshake(Parser::BinaryTokenizer &tk);
68
69 uint8_t msg_type; ///< see HandshakeType
70 SBuf msg_body; ///< Handshake Protocol message
71 };
72
73 /// TLS Alert protocol frame from RFC 5246 Section 7.2.
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; ///< warning or fatal
82 uint8_t description; ///< close_notify, unexpected_message, etc.
83 };
84
85 /// The size of the TLS Random structure from RFC 5246 Section 7.4.1.2.
86 static const uint64_t HelloRandomSize = 32;
87
88 /// TLS Hello Extension from RFC 5246 Section 7.4.1.4.
89 class Extension
90 {
91 public:
92 typedef uint16_t Type;
93 explicit Extension(Parser::BinaryTokenizer &tk);
94
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;
98
99 Type type;
100 SBuf data;
101 };
102
103 /// Extension types optimized for fast lookups.
104 typedef std::unordered_set<Extension::Type> Extensions;
105 static Extensions SupportedExtensions();
106
107 } // namespace Security
108
109 /// Convenience helper: We parse ProtocolVersion but store "int".
110 static AnyP::ProtocolVersion
111 ParseProtocolVersion(Parser::BinaryTokenizer &tk)
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)
117 return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0);
118
119 Must(vMajor == 3);
120 if (vMinor == 0)
121 return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 3, 0);
122
123 return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, (vMinor - 1));
124 }
125
126 Security::TLSPlaintext::TLSPlaintext(Parser::BinaryTokenizer &tk)
127 {
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");
134 context.success();
135 }
136
137 Security::Handshake::Handshake(Parser::BinaryTokenizer &tk)
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
145 Security::Alert::Alert(Parser::BinaryTokenizer &tk)
146 {
147 Parser::BinaryTokenizerContext context(tk, "Alert");
148 level = tk.uint8(".level");
149 description = tk.uint8(".description");
150 context.success();
151 }
152
153 Security::Extension::Extension(Parser::BinaryTokenizer &tk)
154 {
155 Parser::BinaryTokenizerContext context(tk, "Extension");
156 type = tk.uint16(".type");
157 data = tk.pstring16(".data");
158 context.success();
159 }
160
161 bool
162 Security::Extension::supported() const
163 {
164 static const Extensions supportedExtensions = SupportedExtensions();
165 return supportedExtensions.find(type) != supportedExtensions.end();
166 }
167
168 Security::Sslv2Record::Sslv2Record(Parser::BinaryTokenizer &tk)
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
178 Security::TlsDetails::TlsDetails():
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
190 Security::HandshakeParser::HandshakeParser():
191 details(new TlsDetails),
192 state(atHelloNone),
193 resumingSession(false),
194 currentContentType(0),
195 done(nullptr),
196 expectingModernRecords(false)
197 {
198 }
199
200 void
201 Security::HandshakeParser::parseVersion2Record()
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
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
213 bool
214 Security::HandshakeParser::isSslv2Record(const SBuf &raw) const
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
224 Security::HandshakeParser::parseRecord()
225 {
226 if (expectingModernRecords)
227 parseModernRecord();
228 else
229 parseVersion2Record();
230 }
231
232 /// parses a single TLS Record Layer frame
233 void
234 Security::HandshakeParser::parseModernRecord()
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 parseMessages();
248 Must(tkMessages.atEnd()); // no currentContentType leftovers
249 fragments = record.fragment;
250 currentContentType = record.type;
251 } else {
252 fragments.append(record.fragment);
253 }
254
255 if (tkRecords.atEnd() && !done)
256 parseMessages();
257 }
258
259 /// parses one or more "higher-level protocol" frames of currentContentType
260 void
261 Security::HandshakeParser::parseMessages()
262 {
263 tkMessages.reset(fragments, false);
264 for (; !tkMessages.atEnd(); tkMessages.commit()) {
265 switch (currentContentType) {
266 case ContentType::ctChangeCipherSpec:
267 parseChangeCipherCpecMessage();
268 continue;
269 case ContentType::ctAlert:
270 parseAlertMessage();
271 continue;
272 case ContentType::ctHandshake:
273 parseHandshakeMessage();
274 continue;
275 case ContentType::ctApplicationData:
276 parseApplicationDataMessage();
277 continue;
278 }
279 skipMessage("unknown ContentType msg [fragment]");
280 }
281 }
282
283 void
284 Security::HandshakeParser::parseChangeCipherCpecMessage()
285 {
286 Must(currentContentType == ContentType::ctChangeCipherSpec);
287 // We are currently ignoring Change Cipher Spec Protocol messages.
288 skipMessage("ChangeCipherCpec msg [fragment]");
289
290 // Everything after the ChangeCipherCpec message may be encrypted.
291 // Continuing parsing is pointless. Stop here.
292 resumingSession = true;
293 done = "ChangeCipherCpec";
294 }
295
296 void
297 Security::HandshakeParser::parseAlertMessage()
298 {
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));
304 if (alert.fatal())
305 done = "fatal Alert";
306 // else ignore the warning (at least for now)
307 }
308
309 void
310 Security::HandshakeParser::parseHandshakeMessage()
311 {
312 Must(currentContentType == ContentType::ctHandshake);
313
314 const Handshake message(tkMessages);
315
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";
322 return;
323 case HandshakeType::hskServerHello:
324 Must(state < atHelloReceived);
325 parseServerHelloHandshakeMessage(message.msg_body);
326 state = atHelloReceived;
327 return;
328 case HandshakeType::hskCertificate:
329 Must(state < atCertificatesReceived);
330 parseServerCertificates(message.msg_body);
331 state = atCertificatesReceived;
332 return;
333 case HandshakeType::hskServerHelloDone:
334 Must(state < atHelloDoneReceived);
335 // zero-length
336 state = atHelloDoneReceived;
337 done = "ServerHelloDone";
338 return;
339 }
340 debugs(83, 5, "ignoring " << message.msg_body.length() << "-byte type-" <<
341 static_cast<unsigned int>(message.msg_type) << " handshake message");
342 }
343
344 void
345 Security::HandshakeParser::parseApplicationDataMessage()
346 {
347 Must(currentContentType == ContentType::ctApplicationData);
348 skipMessage("app data [fragment]");
349 }
350
351 void
352 Security::HandshakeParser::parseVersion2HandshakeMessage(const SBuf &raw)
353 {
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");
364 hello.success();
365 }
366
367 void
368 Security::HandshakeParser::parseClientHelloHandshakeMessage(const SBuf &raw)
369 {
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"));
379 hello.success();
380 }
381
382 bool
383 Security::HandshakeParser::parseCompressionMethods(const SBuf &raw)
384 {
385 if (raw.length() == 0)
386 return false;
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)
392 return true;
393 }
394 return false;
395 }
396
397 void
398 Security::HandshakeParser::parseExtensions(const SBuf &raw)
399 {
400 Parser::BinaryTokenizer tk(raw);
401 while (!tk.atEnd()) {
402 Extension extension(tk);
403
404 if (!details->unsupportedExtensions && !extension.supported()) {
405 debugs(83, 5, "first unsupported extension: " << extension.type);
406 details->unsupportedExtensions = true;
407 }
408
409 switch(extension.type) {
410 case 0: // The SNI extension; RFC 6066, Section 3
411 details->serverName = parseSniExtension(extension.data);
412 break;
413 case 5: // Certificate Status Request; RFC 6066, Section 8
414 details->tlsStatusRequest = true;
415 break;
416 case 15: // The heartBeats, RFC 6520
417 details->doHeartBeats = true;
418 break;
419 case 16: { // Application-Layer Protocol Negotiation Extension, RFC 7301
420 Parser::BinaryTokenizer tkAPN(extension.data);
421 details->tlsAppLayerProtoNeg = tkAPN.pstring16("APN");
422 break;
423 }
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?)
428 default:
429 break;
430 }
431 }
432 }
433
434 void
435 Security::HandshakeParser::parseCiphers(const SBuf &raw)
436 {
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);
442 }
443 }
444
445 void
446 Security::HandshakeParser::parseV23Ciphers(const SBuf &raw)
447 {
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");
458 if (prefix == 0)
459 details->ciphers.insert(cipher);
460 }
461 }
462
463 /// RFC 5246 Section 7.4.1.3. Server Hello
464 void
465 Security::HandshakeParser::parseServerHelloHandshakeMessage(const SBuf &raw)
466 {
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"));
476 hello.success();
477 }
478
479 // RFC 6066 Section 3: ServerNameList (may be sent by both clients and servers)
480 SBuf
481 Security::HandshakeParser::parseSniExtension(const SBuf &extensionData) const
482 {
483 // Servers SHOULD send an empty SNI extension, not an empty ServerNameList!
484 if (extensionData.isEmpty())
485 return SBuf();
486
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();
496
497 if (nameType == 0) {
498 debugs(83, 3, "host_name=" << name);
499 return name; // it may be empty
500 }
501 // else we just parsed a new/unsupported NameType which,
502 // according to RFC 6066, MUST begin with a 16-bit length field
503 }
504 return SBuf(); // SNI extension lacks host_name
505 }
506
507 void
508 Security::HandshakeParser::skipMessage(const char *description)
509 {
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);
514 }
515
516 bool
517 Security::HandshakeParser::parseHello(const SBuf &data)
518 {
519 try {
520 if (!expectingModernRecords.configured())
521 expectingModernRecords.configure(!isSslv2Record(data));
522
523 // data contains everything read so far, but we may read more later
524 tkRecords.reinput(data, true);
525 tkRecords.rollback();
526 while (!done)
527 parseRecord();
528 debugs(83, 7, "success; got: " << done);
529 // we are done; tkRecords may have leftovers we are not interested in
530 return true;
531 }
532 catch (const Parser::BinaryTokenizer::InsufficientInput &) {
533 debugs(83, 5, "need more data");
534 return false;
535 }
536 return false; // unreached
537 }
538
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)
543 {
544 Security::CertPointer pCert;
545 #if USE_OPENSSL
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
552 #else
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.
556 #endif
557 assert(pCert);
558 return pCert;
559 }
560
561 void
562 Security::HandshakeParser::parseServerCertificates(const SBuf &raw)
563 {
564 #if USE_OPENSSL
565 Parser::BinaryTokenizer tkList(raw);
566 const SBuf clist = tkList.pstring24("CertificateList");
567 Must(tkList.atEnd()); // no leftovers after all certificates
568
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");
574 }
575 #else
576 debugs(83, 7, "no support for CertificateList parsing; ignoring " << raw.length() << " bytes");
577 #endif
578 }
579
580 /// A helper function to create a set of all supported TLS extensions
581 static
582 Security::Extensions
583 Security::SupportedExtensions()
584 {
585 #if USE_OPENSSL
586
587 // optimize lookup speed by reserving the number of values x3, approximately
588 Security::Extensions extensions(64);
589
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);
595 #endif
596 #if defined(TLSEXT_TYPE_max_fragment_length) // 1
597 extensions.insert(TLSEXT_TYPE_max_fragment_length);
598 #endif
599 #if defined(TLSEXT_TYPE_client_certificate_url) // 2
600 extensions.insert(TLSEXT_TYPE_client_certificate_url);
601 #endif
602 #if defined(TLSEXT_TYPE_trusted_ca_keys) // 3
603 extensions.insert(TLSEXT_TYPE_trusted_ca_keys);
604 #endif
605 #if defined(TLSEXT_TYPE_truncated_hmac) // 4
606 extensions.insert(TLSEXT_TYPE_truncated_hmac);
607 #endif
608 #if defined(TLSEXT_TYPE_status_request) // 5
609 extensions.insert(TLSEXT_TYPE_status_request);
610 #endif
611 #if defined(TLSEXT_TYPE_user_mapping) // 6
612 extensions.insert(TLSEXT_TYPE_user_mapping);
613 #endif
614 #if defined(TLSEXT_TYPE_client_authz) // 7
615 extensions.insert(TLSEXT_TYPE_client_authz);
616 #endif
617 #if defined(TLSEXT_TYPE_server_authz) // 8
618 extensions.insert(TLSEXT_TYPE_server_authz);
619 #endif
620 #if defined(TLSEXT_TYPE_cert_type) // 9
621 extensions.insert(TLSEXT_TYPE_cert_type);
622 #endif
623 #if defined(TLSEXT_TYPE_elliptic_curves) // 10
624 extensions.insert(TLSEXT_TYPE_elliptic_curves);
625 #endif
626 #if defined(TLSEXT_TYPE_ec_point_formats) // 11
627 extensions.insert(TLSEXT_TYPE_ec_point_formats);
628 #endif
629 #if defined(TLSEXT_TYPE_srp) // 12
630 extensions.insert(TLSEXT_TYPE_srp);
631 #endif
632 #if defined(TLSEXT_TYPE_signature_algorithms) // 13
633 extensions.insert(TLSEXT_TYPE_signature_algorithms);
634 #endif
635 #if defined(TLSEXT_TYPE_use_srtp) // 14
636 extensions.insert(TLSEXT_TYPE_use_srtp);
637 #endif
638 #if defined(TLSEXT_TYPE_heartbeat) // 15
639 extensions.insert(TLSEXT_TYPE_heartbeat);
640 #endif
641 #if defined(TLSEXT_TYPE_session_ticket) // 35
642 extensions.insert(TLSEXT_TYPE_session_ticket);
643 #endif
644 #if defined(TLSEXT_TYPE_renegotiate) // 0xff01
645 extensions.insert(TLSEXT_TYPE_renegotiate);
646 #endif
647 #if defined(TLSEXT_TYPE_next_proto_neg) // 13172
648 extensions.insert(TLSEXT_TYPE_next_proto_neg);
649 #endif
650
651 /*
652 * OpenSSL does not support these last extensions by default, but those
653 * building the OpenSSL libraries and/or Squid might define them.
654 */
655
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);
661 #endif
662
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);
667 #endif
668
669 return extensions; // might be empty
670 #else
671
672 return Extensions(); // no extensions are supported without OpenSSL
673 #endif
674 }
675