]> git.ipfire.org Git - thirdparty/squid.git/blob - src/security/Handshake.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / security / Handshake.cc
1 /*
2 * Copyright (C) 1996-2021 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 "sbuf/Stream.h"
13 #include "security/Handshake.h"
14 #if USE_OPENSSL
15 #include "ssl/support.h"
16 #endif
17
18 #include <unordered_set>
19
20 namespace Security {
21 /*
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.
26 */
27
28 /// TLS Record Layer's content types from RFC 5246 Section 6.2.1
29 enum ContentType {
30 ctChangeCipherSpec = 20,
31 ctAlert = 21,
32 ctHandshake = 22,
33 ctApplicationData = 23
34 };
35
36 /// TLS Record Layer's frame from RFC 5246 Section 6.2.1.
37 class TLSPlaintext
38 {
39 public:
40 explicit TLSPlaintext(Parser::BinaryTokenizer &tk);
41
42 uint8_t type; ///< see ContentType
43 AnyP::ProtocolVersion version; ///< Record Layer, not necessarily the negotiated TLS version;
44 SBuf fragment; ///< possibly partial content
45 };
46
47 /// draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
48 class Sslv2Record
49 {
50 public:
51 explicit Sslv2Record(Parser::BinaryTokenizer &tk);
52
53 SBuf fragment;
54 };
55
56 /// TLS Handshake protocol's handshake types from RFC 5246 Section 7.4
57 enum HandshakeType {
58 hskClientHello = 1,
59 hskServerHello = 2,
60 hskCertificate = 11,
61 hskServerHelloDone = 14
62 };
63
64 /// TLS Handshake Protocol frame from RFC 5246 Section 7.4.
65 class Handshake
66 {
67 public:
68 explicit Handshake(Parser::BinaryTokenizer &tk);
69
70 uint8_t msg_type; ///< see HandshakeType
71 SBuf msg_body; ///< Handshake Protocol message
72 };
73
74 /// TLS Alert protocol frame from RFC 5246 Section 7.2.
75 class Alert
76 {
77 public:
78 explicit Alert(Parser::BinaryTokenizer &tk);
79
80 bool fatal() const { return level == 2; }
81
82 uint8_t level; ///< warning or fatal
83 uint8_t description; ///< close_notify, unexpected_message, etc.
84 };
85
86 /// The size of the TLS Random structure from RFC 5246 Section 7.4.1.2.
87 static const uint64_t HelloRandomSize = 32;
88
89 /// TLS Hello Extension from RFC 5246 Section 7.4.1.4.
90 class Extension
91 {
92 public:
93 typedef uint16_t Type;
94 explicit Extension(Parser::BinaryTokenizer &tk);
95
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;
99
100 Type type;
101 SBuf data;
102 };
103
104 /// Extension types optimized for fast lookups.
105 typedef std::unordered_set<Extension::Type> Extensions;
106 static Extensions SupportedExtensions();
107
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)
112 {
113 Parser::BinaryTokenizerContext context(tk, contextLabel);
114 uint8_t vMajor = tk.uint8(".major");
115 uint8_t vMinor = tk.uint8(".minor");
116
117 if (vMajor == 0 && vMinor == 2)
118 return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0);
119
120 if (vMajor == 3) {
121 if (vMinor == 0)
122 return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 3, 0);
123 return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, (vMinor - 1));
124 }
125
126 /* handle unsupported versions */
127
128 const uint16_t vRaw = (vMajor << 8) | vMinor;
129 debugs(83, 7, "unsupported: " << asHex(vRaw));
130 if (beStrict)
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();
134 }
135
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)
140 {
141 return ParseProtocolVersionBase(tk, ".version", true);
142 }
143
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)
148 {
149 return ParseProtocolVersionBase(tk, contextLabel, false);
150 }
151
152 } // namespace Security
153
154 Security::TLSPlaintext::TLSPlaintext(Parser::BinaryTokenizer &tk)
155 {
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");
162 context.success();
163 }
164
165 Security::Handshake::Handshake(Parser::BinaryTokenizer &tk)
166 {
167 Parser::BinaryTokenizerContext context(tk, "Handshake");
168 msg_type = tk.uint8(".msg_type");
169 msg_body = tk.pstring24(".msg_body");
170 context.success();
171 }
172
173 Security::Alert::Alert(Parser::BinaryTokenizer &tk)
174 {
175 Parser::BinaryTokenizerContext context(tk, "Alert");
176 level = tk.uint8(".level");
177 description = tk.uint8(".description");
178 context.success();
179 }
180
181 Security::Extension::Extension(Parser::BinaryTokenizer &tk)
182 {
183 Parser::BinaryTokenizerContext context(tk, "Extension");
184 type = tk.uint16(".type");
185 data = tk.pstring16(".data");
186 context.success();
187 }
188
189 bool
190 Security::Extension::supported() const
191 {
192 static const Extensions supportedExtensions = SupportedExtensions();
193 return supportedExtensions.find(type) != supportedExtensions.end();
194 }
195
196 Security::Sslv2Record::Sslv2Record(Parser::BinaryTokenizer &tk)
197 {
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");
203 context.success();
204 }
205
206 Security::TlsDetails::TlsDetails():
207 compressionSupported(false),
208 doHeartBeats(false),
209 tlsTicketsExtension(false),
210 hasTlsTicket(false),
211 tlsStatusRequest(false),
212 unsupportedExtensions(false)
213 {
214 }
215
216 /* Security::HandshakeParser */
217
218 Security::HandshakeParser::HandshakeParser(const MessageSource source):
219 details(new TlsDetails),
220 state(atHelloNone),
221 resumingSession(false),
222 messageSource(source),
223 currentContentType(0),
224 done(nullptr),
225 expectingModernRecords(false)
226 {
227 }
228
229 void
230 Security::HandshakeParser::parseVersion2Record()
231 {
232 const Sslv2Record record(tkRecords);
233 tkRecords.commit();
234 details->tlsVersion = AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0);
235 parseVersion2HandshakeMessage(record.fragment);
236 state = atHelloReceived;
237 done = "SSLv2";
238 }
239
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
242 bool
243 Security::HandshakeParser::isSslv2Record(const SBuf &raw) const
244 {
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;
250 }
251
252 void
253 Security::HandshakeParser::parseRecord()
254 {
255 if (expectingModernRecords)
256 parseModernRecord();
257 else
258 parseVersion2Record();
259 }
260
261 /// parses a single TLS Record Layer frame
262 void
263 Security::HandshakeParser::parseModernRecord()
264 {
265 const TLSPlaintext record(tkRecords);
266 tkRecords.commit();
267
268 details->tlsVersion = record.version;
269
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);
274
275 if (currentContentType != record.type) {
276 parseMessages();
277 Must(tkMessages.atEnd()); // no currentContentType leftovers
278 fragments = record.fragment;
279 currentContentType = record.type;
280 } else {
281 fragments.append(record.fragment);
282 }
283
284 if (tkRecords.atEnd() && !done)
285 parseMessages();
286 }
287
288 /// parses one or more "higher-level protocol" frames of currentContentType
289 void
290 Security::HandshakeParser::parseMessages()
291 {
292 tkMessages.reset(fragments, false);
293 for (; !tkMessages.atEnd(); tkMessages.commit()) {
294 switch (currentContentType) {
295 case ContentType::ctChangeCipherSpec:
296 parseChangeCipherCpecMessage();
297 continue;
298 case ContentType::ctAlert:
299 parseAlertMessage();
300 continue;
301 case ContentType::ctHandshake:
302 parseHandshakeMessage();
303 continue;
304 case ContentType::ctApplicationData:
305 parseApplicationDataMessage();
306 continue;
307 }
308 skipMessage("unknown ContentType msg [fragment]");
309 }
310 }
311
312 void
313 Security::HandshakeParser::parseChangeCipherCpecMessage()
314 {
315 Must(currentContentType == ContentType::ctChangeCipherSpec);
316 // We are currently ignoring Change Cipher Spec Protocol messages.
317 skipMessage("ChangeCipherSpec msg [fragment]");
318
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))
324 return;
325
326 resumingSession = true;
327
328 // Everything after the ChangeCipherSpec message may be encrypted. Stop.
329 done = "ChangeCipherSpec in v1.2-";
330 }
331
332 void
333 Security::HandshakeParser::parseAlertMessage()
334 {
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));
340 if (alert.fatal())
341 done = "fatal Alert";
342 // else ignore the warning (at least for now)
343 }
344
345 void
346 Security::HandshakeParser::parseHandshakeMessage()
347 {
348 Must(currentContentType == ContentType::ctHandshake);
349
350 const Handshake message(tkMessages);
351
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";
359 return;
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+";
368 return;
369 case HandshakeType::hskServerHelloDone:
370 Must(state < atHelloDoneReceived);
371 // zero-length
372 state = atHelloDoneReceived;
373 done = "ServerHelloDone";
374 return;
375 }
376 debugs(83, 5, "ignoring " << message.msg_body.length() << "-byte type-" <<
377 static_cast<unsigned int>(message.msg_type) << " handshake message");
378 }
379
380 void
381 Security::HandshakeParser::parseApplicationDataMessage()
382 {
383 Must(currentContentType == ContentType::ctApplicationData);
384 skipMessage("app data [fragment]");
385 }
386
387 void
388 Security::HandshakeParser::parseVersion2HandshakeMessage(const SBuf &raw)
389 {
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");
400 hello.success();
401 }
402
403 void
404 Security::HandshakeParser::parseClientHelloHandshakeMessage(const SBuf &raw)
405 {
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"));
415 hello.success();
416 }
417
418 bool
419 Security::HandshakeParser::parseCompressionMethods(const SBuf &raw)
420 {
421 if (raw.length() == 0)
422 return false;
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)
428 return true;
429 }
430 return false;
431 }
432
433 void
434 Security::HandshakeParser::parseExtensions(const SBuf &raw)
435 {
436 Parser::BinaryTokenizer tk(raw);
437 while (!tk.atEnd()) {
438 Extension extension(tk);
439
440 if (!details->unsupportedExtensions && !extension.supported()) {
441 debugs(83, 5, "first unsupported extension: " << extension.type);
442 details->unsupportedExtensions = true;
443 }
444
445 switch(extension.type) {
446 case 0: // The SNI extension; RFC 6066, Section 3
447 details->serverName = parseSniExtension(extension.data);
448 break;
449 case 5: // Certificate Status Request; RFC 6066, Section 8
450 details->tlsStatusRequest = true;
451 break;
452 case 15: // The heartBeats, RFC 6520
453 details->doHeartBeats = true;
454 break;
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");
460 break;
461 }
462 case 35: // SessionTicket TLS Extension; RFC 5077
463 details->tlsTicketsExtension = true;
464 details->hasTlsTicket = !extension.data.isEmpty();
465 break;
466 case 43: // supported_versions extension; RFC 8446
467 parseSupportedVersionsExtension(extension.data);
468 break;
469 default:
470 // other extensions, including those that Squid does not support, do
471 // not require special handling here, but see unsupportedExtensions
472 break;
473 }
474 }
475 }
476
477 void
478 Security::HandshakeParser::parseCiphers(const SBuf &raw)
479 {
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
485 }
486 }
487
488 void
489 Security::HandshakeParser::parseV23Ciphers(const SBuf &raw)
490 {
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");
501 if (prefix == 0)
502 details->ciphers.insert(cipher); // including Squid-unsupported ones
503 }
504 }
505
506 /// RFC 5246 Section 7.4.1.3. Server Hello
507 void
508 Security::HandshakeParser::parseServerHelloHandshakeMessage(const SBuf &raw)
509 {
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"));
520 hello.success();
521 }
522
523 // RFC 6066 Section 3: ServerNameList (may be sent by both clients and servers)
524 SBuf
525 Security::HandshakeParser::parseSniExtension(const SBuf &extensionData) const
526 {
527 // Servers SHOULD send an empty SNI extension, not an empty ServerNameList!
528 if (extensionData.isEmpty())
529 return SBuf();
530
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();
540
541 if (nameType == 0) {
542 debugs(83, 3, "host_name=" << name);
543 return name; // it may be empty
544 }
545 // else we just parsed a new/unsupported NameType which,
546 // according to RFC 6066, MUST begin with a 16-bit length field
547 }
548 return SBuf(); // SNI extension lacks host_name
549 }
550
551 /// RFC 8446 Section 4.2.1: SupportedVersions extension
552 void
553 Security::HandshakeParser::parseSupportedVersionsExtension(const SBuf &extensionData) const
554 {
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.
560
561 // Please note that several of these MUSTs also imply certain likely
562 // handling of a hypothetical next TLS version (e.g., v1.4).
563
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.
568 //
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
573 // (TLS 1.2).
574 //
575 // Ignore supported_versions senders violating legacy_version MUSTs above:
576 if (details->tlsSupportedVersion != AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, 2))
577 return;
578
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
586 if (!version)
587 continue;
588 if (!supportedVersionMax || TlsVersionEarlierThan(supportedVersionMax, version))
589 supportedVersionMax = version;
590 }
591
592 // ignore empty and ignored-values-only supported_versions
593 if (!supportedVersionMax)
594 return;
595
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.
599 } else {
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.
605 if (!version)
606 return;
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))
611 return;
612 supportedVersionMax = version;
613 }
614
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).
619 //
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;
628 }
629
630 void
631 Security::HandshakeParser::skipMessage(const char *description)
632 {
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);
637 }
638
639 bool
640 Security::HandshakeParser::parseHello(const SBuf &data)
641 {
642 try {
643 if (!expectingModernRecords.configured())
644 expectingModernRecords.configure(!isSslv2Record(data));
645
646 // data contains everything read so far, but we may read more later
647 tkRecords.reinput(data, true);
648 tkRecords.rollback();
649 while (!done)
650 parseRecord();
651 debugs(83, 7, "success; got: " << done);
652 // we are done; tkRecords may have leftovers we are not interested in
653 return true;
654 }
655 catch (const Parser::BinaryTokenizer::InsufficientInput &) {
656 debugs(83, 5, "need more data");
657 return false;
658 }
659 return false; // unreached
660 }
661
662 /// A helper function to create a set of all supported TLS extensions
663 static
664 Security::Extensions
665 Security::SupportedExtensions()
666 {
667 #if USE_OPENSSL
668
669 // optimize lookup speed by reserving the number of values x3, approximately
670 Security::Extensions extensions(64);
671
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);
677 #endif
678 #if defined(TLSEXT_TYPE_max_fragment_length) // 1
679 extensions.insert(TLSEXT_TYPE_max_fragment_length);
680 #endif
681 #if defined(TLSEXT_TYPE_client_certificate_url) // 2
682 extensions.insert(TLSEXT_TYPE_client_certificate_url);
683 #endif
684 #if defined(TLSEXT_TYPE_trusted_ca_keys) // 3
685 extensions.insert(TLSEXT_TYPE_trusted_ca_keys);
686 #endif
687 #if defined(TLSEXT_TYPE_truncated_hmac) // 4
688 extensions.insert(TLSEXT_TYPE_truncated_hmac);
689 #endif
690 #if defined(TLSEXT_TYPE_status_request) // 5
691 extensions.insert(TLSEXT_TYPE_status_request);
692 #endif
693 #if defined(TLSEXT_TYPE_user_mapping) // 6
694 extensions.insert(TLSEXT_TYPE_user_mapping);
695 #endif
696 #if defined(TLSEXT_TYPE_client_authz) // 7
697 extensions.insert(TLSEXT_TYPE_client_authz);
698 #endif
699 #if defined(TLSEXT_TYPE_server_authz) // 8
700 extensions.insert(TLSEXT_TYPE_server_authz);
701 #endif
702 #if defined(TLSEXT_TYPE_cert_type) // 9
703 extensions.insert(TLSEXT_TYPE_cert_type);
704 #endif
705 #if defined(TLSEXT_TYPE_elliptic_curves) // 10
706 extensions.insert(TLSEXT_TYPE_elliptic_curves);
707 #endif
708 #if defined(TLSEXT_TYPE_ec_point_formats) // 11
709 extensions.insert(TLSEXT_TYPE_ec_point_formats);
710 #endif
711 #if defined(TLSEXT_TYPE_srp) // 12
712 extensions.insert(TLSEXT_TYPE_srp);
713 #endif
714 #if defined(TLSEXT_TYPE_signature_algorithms) // 13
715 extensions.insert(TLSEXT_TYPE_signature_algorithms);
716 #endif
717 #if defined(TLSEXT_TYPE_use_srtp) // 14
718 extensions.insert(TLSEXT_TYPE_use_srtp);
719 #endif
720 #if defined(TLSEXT_TYPE_heartbeat) // 15
721 extensions.insert(TLSEXT_TYPE_heartbeat);
722 #endif
723 #if defined(TLSEXT_TYPE_session_ticket) // 35
724 extensions.insert(TLSEXT_TYPE_session_ticket);
725 #endif
726 #if defined(TLSEXT_TYPE_renegotiate) // 0xff01
727 extensions.insert(TLSEXT_TYPE_renegotiate);
728 #endif
729 #if defined(TLSEXT_TYPE_next_proto_neg) // 13172
730 extensions.insert(TLSEXT_TYPE_next_proto_neg);
731 #endif
732 #if defined(TLSEXT_TYPE_supported_versions) // 43
733 extensions.insert(TLSEXT_TYPE_supported_versions);
734 #endif
735
736 /*
737 * OpenSSL does not support these last extensions by default, but those
738 * building the OpenSSL libraries and/or Squid might define them.
739 */
740
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);
746 #endif
747
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);
752 #endif
753
754 return extensions; // might be empty
755 #else
756
757 return Extensions(); // no extensions are supported without OpenSSL
758 #endif
759 }
760