]> git.ipfire.org Git - thirdparty/squid.git/blame - src/security/Handshake.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / security / Handshake.cc
CommitLineData
a804b6fe 1/*
4ac4a490 2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
a804b6fe
AR
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
9210f5ec 11#include "squid.h"
9210f5ec
CT
12#include "security/Handshake.h"
13#if USE_OPENSSL
14#include "ssl/support.h"
15#endif
16
c05c0c94
AR
17#include <unordered_set>
18
a804b6fe 19namespace Security {
fde0b2ca 20/*
a804b6fe
AR
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
28enum 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.
36class TLSPlaintext
37{
38public:
67c99fc6 39 explicit TLSPlaintext(Parser::BinaryTokenizer &tk);
a804b6fe
AR
40
41 uint8_t type; ///< see ContentType
67c99fc6 42 AnyP::ProtocolVersion version; ///< Record Layer, not necessarily the negotiated TLS version;
a804b6fe
AR
43 SBuf fragment; ///< possibly partial content
44};
45
46/// draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
47class Sslv2Record
48{
49public:
67c99fc6 50 explicit Sslv2Record(Parser::BinaryTokenizer &tk);
a804b6fe
AR
51
52 SBuf fragment;
53};
54
55/// TLS Handshake protocol's handshake types from RFC 5246 Section 7.4
56enum 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.
64class Handshake
65{
66public:
67c99fc6 67 explicit Handshake(Parser::BinaryTokenizer &tk);
a804b6fe
AR
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.
74class Alert
75{
76public:
67c99fc6 77 explicit Alert(Parser::BinaryTokenizer &tk);
a804b6fe
AR
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.
86static const uint64_t HelloRandomSize = 32;
87
88/// TLS Hello Extension from RFC 5246 Section 7.4.1.4.
89class Extension
90{
91public:
c05c0c94 92 typedef uint16_t Type;
67c99fc6 93 explicit Extension(Parser::BinaryTokenizer &tk);
a804b6fe 94
c05c0c94
AR
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;
a804b6fe
AR
100 SBuf data;
101};
102
c05c0c94
AR
103/// Extension types optimized for fast lookups.
104typedef std::unordered_set<Extension::Type> Extensions;
105static Extensions SupportedExtensions();
106
a804b6fe
AR
107} // namespace Security
108
109/// Convenience helper: We parse ProtocolVersion but store "int".
67c99fc6
CT
110static AnyP::ProtocolVersion
111ParseProtocolVersion(Parser::BinaryTokenizer &tk)
a804b6fe 112{
67c99fc6
CT
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);
6821c276 118
67c99fc6
CT
119 Must(vMajor == 3);
120 if (vMinor == 0)
121 return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 3, 0);
a804b6fe 122
67c99fc6 123 return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, (vMinor - 1));
9210f5ec
CT
124}
125
67c99fc6 126Security::TLSPlaintext::TLSPlaintext(Parser::BinaryTokenizer &tk)
6821c276 127{
67c99fc6 128 Parser::BinaryTokenizerContext context(tk, "TLSPlaintext");
a804b6fe 129 type = tk.uint8(".type");
21530947 130 Must(type >= ctChangeCipherSpec && type <= ctApplicationData);
a804b6fe
AR
131 version = ParseProtocolVersion(tk);
132 // TODO: Must(version.major == 3);
133 fragment = tk.pstring16(".fragment");
c3149111 134 context.success();
9210f5ec
CT
135}
136
67c99fc6 137Security::Handshake::Handshake(Parser::BinaryTokenizer &tk)
9210f5ec 138{
67c99fc6 139 Parser::BinaryTokenizerContext context(tk, "Handshake");
a804b6fe
AR
140 msg_type = tk.uint8(".msg_type");
141 msg_body = tk.pstring24(".msg_body");
c3149111 142 context.success();
9210f5ec
CT
143}
144
67c99fc6 145Security::Alert::Alert(Parser::BinaryTokenizer &tk)
9210f5ec 146{
67c99fc6 147 Parser::BinaryTokenizerContext context(tk, "Alert");
a804b6fe
AR
148 level = tk.uint8(".level");
149 description = tk.uint8(".description");
c3149111 150 context.success();
9210f5ec
CT
151}
152
67c99fc6 153Security::Extension::Extension(Parser::BinaryTokenizer &tk)
9210f5ec 154{
67c99fc6 155 Parser::BinaryTokenizerContext context(tk, "Extension");
a804b6fe
AR
156 type = tk.uint16(".type");
157 data = tk.pstring16(".data");
c3149111 158 context.success();
9210f5ec
CT
159}
160
c05c0c94
AR
161bool
162Security::Extension::supported() const
9210f5ec 163{
c05c0c94
AR
164 static const Extensions supportedExtensions = SupportedExtensions();
165 return supportedExtensions.find(type) != supportedExtensions.end();
9210f5ec
CT
166}
167
67c99fc6 168Security::Sslv2Record::Sslv2Record(Parser::BinaryTokenizer &tk)
9210f5ec 169{
67c99fc6 170 Parser::BinaryTokenizerContext context(tk, "Sslv2Record");
c3149111 171 const uint16_t head = tk.uint16(".head");
a804b6fe 172 const uint16_t length = head & 0x7FFF;
79d1813c 173 Must((head & 0x8000) && length); // SSLv2 message [without padding]
8abcff99 174 fragment = tk.area(length, ".fragment");
c3149111 175 context.success();
9210f5ec
CT
176}
177
f0f2a850 178Security::TlsDetails::TlsDetails():
67c99fc6 179 compressionSupported(false),
3ee91b7b 180 doHeartBeats(false),
f0f2a850
CT
181 tlsTicketsExtension(false),
182 hasTlsTicket(false),
c05c0c94
AR
183 tlsStatusRequest(false),
184 unsupportedExtensions(false)
9210f5ec 185{
6821c276 186}
9210f5ec 187
015cf86c 188/* Security::HandshakeParser */
9210f5ec 189
015cf86c 190Security::HandshakeParser::HandshakeParser():
67c99fc6 191 details(new TlsDetails),
015cf86c 192 state(atHelloNone),
d9219c2b 193 resumingSession(false),
015cf86c 194 currentContentType(0),
d20cf186 195 done(nullptr),
015cf86c 196 expectingModernRecords(false)
9210f5ec 197{
9210f5ec
CT
198}
199
8abcff99
CT
200void
201Security::HandshakeParser::parseVersion2Record()
202{
203 const Sslv2Record record(tkRecords);
c3149111 204 tkRecords.commit();
67c99fc6 205 details->tlsVersion = AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0);
8abcff99
CT
206 parseVersion2HandshakeMessage(record.fragment);
207 state = atHelloReceived;
c3149111 208 done = "SSLv2";
8abcff99
CT
209}
210
5ea53436 211/// RFC 5246. Appendix E.2. Compatibility with SSL 2.0
c3149111 212/// And draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
21530947 213bool
5ea53436 214Security::HandshakeParser::isSslv2Record(const SBuf &raw) const
21530947 215{
67c99fc6 216 Parser::BinaryTokenizer tk(raw, true);
c3149111
AR
217 const uint16_t head = tk.uint16("?v2Hello.msg_head");
218 const uint8_t type = tk.uint8("?v2Hello.msg_type");
5ea53436
AR
219 const uint16_t length = head & 0x7FFF;
220 return (head & 0x8000) && length && type == 1;
21530947
CT
221}
222
9210f5ec
CT
223void
224Security::HandshakeParser::parseRecord()
6821c276 225{
8abcff99
CT
226 if (expectingModernRecords)
227 parseModernRecord();
228 else
229 parseVersion2Record();
230}
21530947 231
8abcff99
CT
232/// parses a single TLS Record Layer frame
233void
234Security::HandshakeParser::parseModernRecord()
9210f5ec
CT
235{
236 const TLSPlaintext record(tkRecords);
c3149111 237 tkRecords.commit();
9210f5ec 238
a804b6fe 239 details->tlsVersion = record.version;
9210f5ec 240
a804b6fe
AR
241 // RFC 5246: length MUST NOT exceed 2^14
242 Must(record.fragment.length() <= (1 << 14));
9210f5ec 243 // RFC 5246: MUST NOT send zero-length [non-application] fragments
a804b6fe 244 Must(record.fragment.length() || record.type == ContentType::ctApplicationData);
9210f5ec
CT
245
246 if (currentContentType != record.type) {
247 Must(tkMessages.atEnd()); // no currentContentType leftovers
248 fragments = record.fragment;
19928af1 249 tkMessages.reset(fragments, true); // true because more fragments may come
9210f5ec
CT
250 currentContentType = record.type;
251 } else {
252 fragments.append(record.fragment);
19928af1 253 tkMessages.reinput(fragments, true); // true because more fragments may come
9210f5ec
CT
254 tkMessages.rollback();
255 }
256 parseMessages();
257}
258
259/// parses one or more "higher-level protocol" frames of currentContentType
260void
261Security::HandshakeParser::parseMessages()
262{
c3149111 263 for (; !tkMessages.atEnd(); tkMessages.commit()) {
9210f5ec
CT
264 switch (currentContentType) {
265 case ContentType::ctChangeCipherSpec:
266 parseChangeCipherCpecMessage();
267 continue;
268 case ContentType::ctAlert:
269 parseAlertMessage();
270 continue;
271 case ContentType::ctHandshake:
272 parseHandshakeMessage();
273 continue;
274 case ContentType::ctApplicationData:
275 parseApplicationDataMessage();
276 continue;
277 }
d9219c2b 278 skipMessage("unknown ContentType msg [fragment]");
9210f5ec
CT
279 }
280}
281
282void
283Security::HandshakeParser::parseChangeCipherCpecMessage()
284{
285 Must(currentContentType == ContentType::ctChangeCipherSpec);
d20cf186 286 // We are currently ignoring Change Cipher Spec Protocol messages.
d9219c2b 287 skipMessage("ChangeCipherCpec msg [fragment]");
fde0b2ca 288
d20cf186
AR
289 // Everything after the ChangeCipherCpec message may be encrypted.
290 // Continuing parsing is pointless. Stop here.
d9219c2b 291 resumingSession = true;
d20cf186 292 done = "ChangeCipherCpec";
9210f5ec
CT
293}
294
295void
296Security::HandshakeParser::parseAlertMessage()
297{
298 Must(currentContentType == ContentType::ctAlert);
299 const Alert alert(tkMessages);
c3149111
AR
300 debugs(83, (alert.fatal() ? 2:3),
301 "level " << static_cast<int>(alert.level) <<
302 " description " << static_cast<int>(alert.description));
793b1bfb
AR
303 if (alert.fatal())
304 done = "fatal Alert";
305 // else ignore the warning (at least for now)
9210f5ec
CT
306}
307
308void
309Security::HandshakeParser::parseHandshakeMessage()
310{
311 Must(currentContentType == ContentType::ctHandshake);
312
313 const Handshake message(tkMessages);
314
315 switch (message.msg_type) {
fde0b2ca
CT
316 case HandshakeType::hskClientHello:
317 Must(state < atHelloReceived);
318 Security::HandshakeParser::parseClientHelloHandshakeMessage(message.msg_body);
319 state = atHelloReceived;
320 done = "ClientHello";
321 return;
322 case HandshakeType::hskServerHello:
323 Must(state < atHelloReceived);
324 parseServerHelloHandshakeMessage(message.msg_body);
325 state = atHelloReceived;
326 return;
327 case HandshakeType::hskCertificate:
328 Must(state < atCertificatesReceived);
0bffe3ce 329 parseServerCertificates(message.msg_body);
fde0b2ca
CT
330 state = atCertificatesReceived;
331 return;
332 case HandshakeType::hskServerHelloDone:
333 Must(state < atHelloDoneReceived);
334 // zero-length
335 state = atHelloDoneReceived;
336 done = "ServerHelloDone";
337 return;
9210f5ec 338 }
c05c0c94 339 debugs(83, 5, "ignoring " << message.msg_body.length() << "-byte type-" <<
38eba0f7 340 static_cast<unsigned int>(message.msg_type) << " handshake message");
9210f5ec
CT
341}
342
343void
344Security::HandshakeParser::parseApplicationDataMessage()
345{
346 Must(currentContentType == ContentType::ctApplicationData);
d9219c2b 347 skipMessage("app data [fragment]");
6821c276
CT
348}
349
f0f2a850
CT
350void
351Security::HandshakeParser::parseVersion2HandshakeMessage(const SBuf &raw)
352{
67c99fc6
CT
353 Parser::BinaryTokenizer tk(raw);
354 Parser::BinaryTokenizerContext hello(tk, "V2ClientHello");
c3149111 355 Must(tk.uint8(".type") == hskClientHello); // Only client hello supported.
a804b6fe 356 details->tlsSupportedVersion = ParseProtocolVersion(tk);
c3149111
AR
357 const uint16_t ciphersLen = tk.uint16(".cipher_specs.length");
358 const uint16_t sessionIdLen = tk.uint16(".session_id.length");
359 const uint16_t challengeLen = tk.uint16(".challenge.length");
360 parseV23Ciphers(tk.area(ciphersLen, ".cipher_specs.body"));
361 details->sessionId = tk.area(sessionIdLen, ".session_id.body");
362 tk.skip(challengeLen, ".challenge.body");
363 hello.success();
f0f2a850
CT
364}
365
366void
367Security::HandshakeParser::parseClientHelloHandshakeMessage(const SBuf &raw)
368{
67c99fc6
CT
369 Parser::BinaryTokenizer tk(raw);
370 Parser::BinaryTokenizerContext hello(tk, "ClientHello");
a804b6fe
AR
371 details->tlsSupportedVersion = ParseProtocolVersion(tk);
372 details->clientRandom = tk.area(HelloRandomSize, ".random");
373 details->sessionId = tk.pstring8(".session_id");
374 parseCiphers(tk.pstring16(".cipher_suites"));
67c99fc6 375 details->compressionSupported = parseCompressionMethods(tk.pstring8(".compression_methods"));
c3149111 376 if (!tk.atEnd()) // extension-free message ends here
a804b6fe 377 parseExtensions(tk.pstring16(".extensions"));
c3149111 378 hello.success();
f0f2a850
CT
379}
380
67c99fc6
CT
381bool
382Security::HandshakeParser::parseCompressionMethods(const SBuf &raw)
383{
384 if (raw.length() == 0)
385 return false;
386 Parser::BinaryTokenizer tk(raw);
387 while (!tk.atEnd()) {
388 // Probably here we should check for DEFLATE(1) compression method
389 // which is the only supported by openSSL subsystem.
390 if (tk.uint8("compression_method") != 0)
391 return true;
392 }
393 return false;
394}
395
f0f2a850
CT
396void
397Security::HandshakeParser::parseExtensions(const SBuf &raw)
398{
67c99fc6 399 Parser::BinaryTokenizer tk(raw);
f0f2a850
CT
400 while (!tk.atEnd()) {
401 Extension extension(tk);
c05c0c94
AR
402
403 if (!details->unsupportedExtensions && !extension.supported()) {
404 debugs(83, 5, "first unsupported extension: " << extension.type);
405 details->unsupportedExtensions = true;
406 }
f0f2a850
CT
407
408 switch(extension.type) {
21f081e2 409 case 0: // The SNI extension; RFC 6066, Section 3
a804b6fe 410 details->serverName = parseSniExtension(extension.data);
f0f2a850 411 break;
79d1813c 412 case 5: // Certificate Status Request; RFC 6066, Section 8
f0f2a850
CT
413 details->tlsStatusRequest = true;
414 break;
79d1813c 415 case 15: // The heartBeats, RFC 6520
f0f2a850
CT
416 details->doHeartBeats = true;
417 break;
79d1813c 418 case 16: { // Application-Layer Protocol Negotiation Extension, RFC 7301
67c99fc6 419 Parser::BinaryTokenizer tkAPN(extension.data);
a804b6fe 420 details->tlsAppLayerProtoNeg = tkAPN.pstring16("APN");
f0f2a850 421 break;
79d1813c
AR
422 }
423 case 35: // SessionTicket TLS Extension; RFC 5077
f0f2a850 424 details->tlsTicketsExtension = true;
a804b6fe 425 details->hasTlsTicket = !extension.data.isEmpty();
79d1813c 426 case 13172: // Next Protocol Negotiation Extension (expired draft?)
f0f2a850
CT
427 default:
428 break;
429 }
430 }
431}
432
433void
434Security::HandshakeParser::parseCiphers(const SBuf &raw)
435{
c05c0c94 436 details->ciphers.reserve(raw.length() / sizeof(uint16_t));
67c99fc6 437 Parser::BinaryTokenizer tk(raw);
f0f2a850
CT
438 while (!tk.atEnd()) {
439 const uint16_t cipher = tk.uint16("cipher");
c05c0c94 440 details->ciphers.insert(cipher);
f0f2a850
CT
441 }
442}
443
444void
445Security::HandshakeParser::parseV23Ciphers(const SBuf &raw)
446{
67c99fc6 447 Parser::BinaryTokenizer tk(raw);
f0f2a850 448 while (!tk.atEnd()) {
28c02f90 449 // RFC 6101 Appendix E, RFC 5246 Appendix E2
fde0b2ca 450 // Unlike TLS, ciphers in SSLv23 Hellos are 3 bytes long and come in
28c02f90
CT
451 // two versions: v2 and v3. The two versions may co-exist in a single
452 // SSLv23 Hello. Only v3 ciphers have a first byte value of zero.
fde0b2ca 453 // The ciphers are needed for our peeking/staring code that
28c02f90 454 // does not support SSLv2, so we ignore v2 ciphers.
f0f2a850
CT
455 const uint8_t prefix = tk.uint8("prefix");
456 const uint16_t cipher = tk.uint16("cipher");
67c99fc6 457 if (prefix == 0)
c05c0c94 458 details->ciphers.insert(cipher);
f0f2a850
CT
459 }
460}
461
c3149111 462/// RFC 5246 Section 7.4.1.3. Server Hello
f0f2a850
CT
463void
464Security::HandshakeParser::parseServerHelloHandshakeMessage(const SBuf &raw)
465{
67c99fc6
CT
466 Parser::BinaryTokenizer tk(raw);
467 Parser::BinaryTokenizerContext hello(tk, "ServerHello");
a804b6fe
AR
468 details->tlsSupportedVersion = ParseProtocolVersion(tk);
469 tk.skip(HelloRandomSize, ".random");
470 details->sessionId = tk.pstring8(".session_id");
c05c0c94 471 details->ciphers.insert(tk.uint16(".cipher_suite"));
67c99fc6 472 details->compressionSupported = tk.uint8(".compression_method") != 0; // not null
c3149111 473 if (!tk.atEnd()) // extensions present
a804b6fe
AR
474 parseExtensions(tk.pstring16(".extensions"));
475 hello.success();
f0f2a850
CT
476}
477
21f081e2
AR
478// RFC 6066 Section 3: ServerNameList (may be sent by both clients and servers)
479SBuf
480Security::HandshakeParser::parseSniExtension(const SBuf &extensionData) const
481{
fc34b43d
AR
482 // Servers SHOULD send an empty SNI extension, not an empty ServerNameList!
483 if (extensionData.isEmpty())
484 return SBuf();
485
21f081e2
AR
486 // SNI MUST NOT contain more than one name of the same name_type but
487 // we ignore violations and simply return the first host name found.
67c99fc6
CT
488 Parser::BinaryTokenizer tkList(extensionData);
489 Parser::BinaryTokenizer tkNames(tkList.pstring16("ServerNameList"));
21f081e2 490 while (!tkNames.atEnd()) {
67c99fc6 491 Parser::BinaryTokenizerContext serverName(tkNames, "ServerName");
c3149111 492 const uint8_t nameType = tkNames.uint8(".name_type");
a804b6fe 493 const SBuf name = tkNames.pstring16(".name");
c3149111
AR
494 serverName.success();
495
21f081e2 496 if (nameType == 0) {
aa6896b4
AR
497 debugs(83, 3, "host_name=" << name);
498 return name; // it may be empty
21f081e2 499 }
aa6896b4 500 // else we just parsed a new/unsupported NameType which,
21f081e2
AR
501 // according to RFC 6066, MUST begin with a 16-bit length field
502 }
c3149111 503 return SBuf(); // SNI extension lacks host_name
9210f5ec
CT
504}
505
506void
507Security::HandshakeParser::skipMessage(const char *description)
508{
509 // tkMessages/fragments can only contain messages of the same ContentType.
510 // To skip a message, we can and should skip everything we have [left]. If
511 // we have partial messages, debugging will mislead about their boundaries.
512 tkMessages.skip(tkMessages.leftovers().length(), description);
9210f5ec
CT
513}
514
9210f5ec 515bool
7706b2ef 516Security::HandshakeParser::parseHello(const SBuf &data)
9210f5ec
CT
517{
518 try {
67c99fc6
CT
519 if (!expectingModernRecords.configured())
520 expectingModernRecords.configure(!isSslv2Record(data));
5ea53436 521
19928af1
AR
522 // data contains everything read so far, but we may read more later
523 tkRecords.reinput(data, true);
9210f5ec 524 tkRecords.rollback();
d20cf186 525 while (!done)
9210f5ec 526 parseRecord();
d20cf186
AR
527 debugs(83, 7, "success; got: " << done);
528 // we are done; tkRecords may have leftovers we are not interested in
529 return true;
9210f5ec 530 }
67c99fc6 531 catch (const Parser::BinaryTokenizer::InsufficientInput &) {
9210f5ec 532 debugs(83, 5, "need more data");
d20cf186 533 return false;
9210f5ec 534 }
d20cf186 535 return false; // unreached
9210f5ec
CT
536}
537
a34d1d2d
CT
538void
539Security::HandshakeParser::ParseCertificate(const SBuf &raw, Security::CertPointer &pCert)
9210f5ec 540{
a34d1d2d 541#if USE_OPENSSL
4b5ea8a6
CT
542 auto x509Start = reinterpret_cast<const unsigned char *>(raw.rawContent());
543 auto x509Pos = x509Start;
9210f5ec 544 X509 *x509 = d2i_X509(nullptr, &x509Pos, raw.length());
561699b3 545 pCert.resetWithoutLocking(x509);
9210f5ec
CT
546 Must(x509); // successfully parsed
547 Must(x509Pos == x509Start + raw.length()); // no leftovers
a34d1d2d 548#endif
9210f5ec
CT
549}
550
551void
552Security::HandshakeParser::parseServerCertificates(const SBuf &raw)
553{
0bffe3ce
CT
554 Parser::BinaryTokenizer tkList(raw);
555 const SBuf clist = tkList.pstring24("CertificateList");
9210f5ec
CT
556 Must(tkList.atEnd()); // no leftovers after all certificates
557
0bffe3ce 558 Parser::BinaryTokenizer tkItems(clist);
9210f5ec 559 while (!tkItems.atEnd()) {
a34d1d2d
CT
560 Security::CertPointer cert;
561 ParseCertificate(tkItems.pstring24("Certificate"), cert);
562 serverCertificates.push_back(cert);
563 debugs(83, 7, "parsed " << serverCertificates.size() << " certificates so far");
9210f5ec
CT
564 }
565
566}
c05c0c94
AR
567
568/// A helper function to create a set of all supported TLS extensions
569static
570Security::Extensions
571Security::SupportedExtensions()
572{
a34d1d2d
CT
573#if USE_OPENSSL
574
c05c0c94
AR
575 // optimize lookup speed by reserving the number of values x3, approximately
576 Security::Extensions extensions(64);
577
578 // Keep this list ordered and up to date by running something like
579 // egrep '# *define TLSEXT_TYPE_' /usr/include/openssl/tls1.h
580 // TODO: Teach OpenSSL to return the list of extensions it supports.
581#if defined(TLSEXT_TYPE_server_name) // 0
582 extensions.insert(TLSEXT_TYPE_server_name);
583#endif
584#if defined(TLSEXT_TYPE_max_fragment_length) // 1
585 extensions.insert(TLSEXT_TYPE_max_fragment_length);
586#endif
587#if defined(TLSEXT_TYPE_client_certificate_url) // 2
588 extensions.insert(TLSEXT_TYPE_client_certificate_url);
589#endif
590#if defined(TLSEXT_TYPE_trusted_ca_keys) // 3
591 extensions.insert(TLSEXT_TYPE_trusted_ca_keys);
592#endif
593#if defined(TLSEXT_TYPE_truncated_hmac) // 4
594 extensions.insert(TLSEXT_TYPE_truncated_hmac);
595#endif
596#if defined(TLSEXT_TYPE_status_request) // 5
597 extensions.insert(TLSEXT_TYPE_status_request);
598#endif
599#if defined(TLSEXT_TYPE_user_mapping) // 6
600 extensions.insert(TLSEXT_TYPE_user_mapping);
601#endif
602#if defined(TLSEXT_TYPE_client_authz) // 7
603 extensions.insert(TLSEXT_TYPE_client_authz);
604#endif
605#if defined(TLSEXT_TYPE_server_authz) // 8
606 extensions.insert(TLSEXT_TYPE_server_authz);
607#endif
608#if defined(TLSEXT_TYPE_cert_type) // 9
609 extensions.insert(TLSEXT_TYPE_cert_type);
610#endif
611#if defined(TLSEXT_TYPE_elliptic_curves) // 10
612 extensions.insert(TLSEXT_TYPE_elliptic_curves);
613#endif
614#if defined(TLSEXT_TYPE_ec_point_formats) // 11
615 extensions.insert(TLSEXT_TYPE_ec_point_formats);
616#endif
617#if defined(TLSEXT_TYPE_srp) // 12
618 extensions.insert(TLSEXT_TYPE_srp);
619#endif
620#if defined(TLSEXT_TYPE_signature_algorithms) // 13
621 extensions.insert(TLSEXT_TYPE_signature_algorithms);
622#endif
623#if defined(TLSEXT_TYPE_use_srtp) // 14
624 extensions.insert(TLSEXT_TYPE_use_srtp);
625#endif
626#if defined(TLSEXT_TYPE_heartbeat) // 15
627 extensions.insert(TLSEXT_TYPE_heartbeat);
628#endif
629#if defined(TLSEXT_TYPE_session_ticket) // 35
630 extensions.insert(TLSEXT_TYPE_session_ticket);
631#endif
632#if defined(TLSEXT_TYPE_renegotiate) // 0xff01
633 extensions.insert(TLSEXT_TYPE_renegotiate);
634#endif
635#if defined(TLSEXT_TYPE_next_proto_neg) // 13172
636 extensions.insert(TLSEXT_TYPE_next_proto_neg);
637#endif
638
639 /*
640 * OpenSSL does not support these last extensions by default, but those
641 * building the OpenSSL libraries and/or Squid might define them.
642 */
643
644 // OpenSSL may be built to support draft-rescorla-tls-opaque-prf-input-00,
645 // with the extension type value configured at build time. OpenSSL, Squid,
646 // and TLS agents must all be built with the same extension type value.
647#if defined(TLSEXT_TYPE_opaque_prf_input)
648 extensions.insert(TLSEXT_TYPE_opaque_prf_input);
649#endif
650
651 // Define this to add extensions supported by your OpenSSL but unknown to
652 // your Squid version. Use {list-initialization} to add multiple extensions.
653#if defined(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID)
654 extensions.insert(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID);
655#endif
656
657 return extensions; // might be empty
f0f2a850 658#else
c05c0c94 659
c05c0c94 660 return Extensions(); // no extensions are supported without OpenSSL
9210f5ec 661#endif
a34d1d2d 662}
fde0b2ca 663