]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/bio.cc
Cleanup: update TLS session pointer types
[thirdparty/squid.git] / src / ssl / bio.cc
1 /*
2 * Copyright (C) 1996-2016 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 accelerator support */
10
11 #include "squid.h"
12 #include "ssl/support.h"
13
14 /* support.cc says this is needed */
15 #if USE_OPENSSL
16
17 #include "comm.h"
18 #include "fde.h"
19 #include "globals.h"
20 #include "ip/Address.h"
21 #include "ssl/bio.h"
22
23 #if HAVE_OPENSSL_SSL_H
24 #include <openssl/ssl.h>
25 #endif
26
27 #if _SQUID_WINDOWS_
28 extern int socket_read_method(int, char *, int);
29 extern int socket_write_method(int, const char *, int);
30 #endif
31
32 /* BIO callbacks */
33 static int squid_bio_write(BIO *h, const char *buf, int num);
34 static int squid_bio_read(BIO *h, char *buf, int size);
35 static int squid_bio_puts(BIO *h, const char *str);
36 //static int squid_bio_gets(BIO *h, char *str, int size);
37 static long squid_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
38 static int squid_bio_create(BIO *h);
39 static int squid_bio_destroy(BIO *data);
40 /* SSL callbacks */
41 static void squid_ssl_info(const SSL *ssl, int where, int ret);
42
43 /// Initialization structure for the BIO table with
44 /// Squid-specific methods and BIO method wrappers.
45 static BIO_METHOD SquidMethods = {
46 BIO_TYPE_SOCKET,
47 "squid",
48 squid_bio_write,
49 squid_bio_read,
50 squid_bio_puts,
51 NULL, // squid_bio_gets not supported
52 squid_bio_ctrl,
53 squid_bio_create,
54 squid_bio_destroy,
55 NULL // squid_callback_ctrl not supported
56 };
57
58 BIO *
59 Ssl::Bio::Create(const int fd, Ssl::Bio::Type type)
60 {
61 if (BIO *bio = BIO_new(&SquidMethods)) {
62 BIO_int_ctrl(bio, BIO_C_SET_FD, type, fd);
63 return bio;
64 }
65 return NULL;
66 }
67
68 void
69 Ssl::Bio::Link(SSL *ssl, BIO *bio)
70 {
71 SSL_set_bio(ssl, bio, bio); // cannot fail
72 SSL_set_info_callback(ssl, &squid_ssl_info); // does not provide diagnostic
73 }
74
75 Ssl::Bio::Bio(const int anFd): fd_(anFd)
76 {
77 debugs(83, 7, "Bio constructed, this=" << this << " FD " << fd_);
78 }
79
80 Ssl::Bio::~Bio()
81 {
82 debugs(83, 7, "Bio destructing, this=" << this << " FD " << fd_);
83 }
84
85 int Ssl::Bio::write(const char *buf, int size, BIO *table)
86 {
87 errno = 0;
88 #if _SQUID_WINDOWS_
89 const int result = socket_write_method(fd_, buf, size);
90 #else
91 const int result = default_write_method(fd_, buf, size);
92 #endif
93 const int xerrno = errno;
94 debugs(83, 5, "FD " << fd_ << " wrote " << result << " <= " << size);
95
96 BIO_clear_retry_flags(table);
97 if (result < 0) {
98 const bool ignoreError = ignoreErrno(xerrno) != 0;
99 debugs(83, 5, "error: " << xerrno << " ignored: " << ignoreError);
100 if (ignoreError)
101 BIO_set_retry_write(table);
102 }
103
104 return result;
105 }
106
107 int
108 Ssl::Bio::read(char *buf, int size, BIO *table)
109 {
110 errno = 0;
111 #if _SQUID_WINDOWS_
112 const int result = socket_read_method(fd_, buf, size);
113 #else
114 const int result = default_read_method(fd_, buf, size);
115 #endif
116 const int xerrno = errno;
117 debugs(83, 5, "FD " << fd_ << " read " << result << " <= " << size);
118
119 BIO_clear_retry_flags(table);
120 if (result < 0) {
121 const bool ignoreError = ignoreErrno(xerrno) != 0;
122 debugs(83, 5, "error: " << xerrno << " ignored: " << ignoreError);
123 if (ignoreError)
124 BIO_set_retry_read(table);
125 }
126
127 return result;
128 }
129
130 int
131 Ssl::Bio::readAndBuffer(char *buf, int size, BIO *table, const char *description)
132 {
133 prepReadBuf();
134
135 size = min((int)rbuf.potentialSpaceSize(), size);
136 if (size <= 0) {
137 debugs(83, DBG_IMPORTANT, "Not enough space to hold " <<
138 rbuf.contentSize() << "+ byte " << description);
139 return -1;
140 }
141
142 const int bytes = Ssl::Bio::read(buf, size, table);
143 debugs(83, 5, "read " << bytes << " out of " << size << " bytes"); // move to Ssl::Bio::read()
144
145 if (bytes > 0) {
146 rbuf.append(buf, bytes);
147 debugs(83, 5, "recorded " << bytes << " bytes of " << description);
148 }
149 return bytes;
150 }
151
152 /// Called whenever the SSL connection state changes, an alert appears, or an
153 /// error occurs. See SSL_set_info_callback().
154 void
155 Ssl::Bio::stateChanged(const SSL *ssl, int where, int ret)
156 {
157 // Here we can use (where & STATE) to check the current state.
158 // Many STATE values are possible, including: SSL_CB_CONNECT_LOOP,
159 // SSL_CB_ACCEPT_LOOP, SSL_CB_HANDSHAKE_START, and SSL_CB_HANDSHAKE_DONE.
160 // For example:
161 // if (where & SSL_CB_HANDSHAKE_START)
162 // debugs(83, 9, "Trying to establish the SSL connection");
163 // else if (where & SSL_CB_HANDSHAKE_DONE)
164 // debugs(83, 9, "SSL connection established");
165
166 debugs(83, 7, "FD " << fd_ << " now: 0x" << std::hex << where << std::dec << ' ' <<
167 SSL_state_string(ssl) << " (" << SSL_state_string_long(ssl) << ")");
168 }
169
170 void
171 Ssl::Bio::prepReadBuf()
172 {
173 if (rbuf.isNull())
174 rbuf.init(4096, 65536);
175 }
176
177 bool
178 Ssl::ClientBio::isClientHello(int state)
179 {
180 return (
181 state == SSL3_ST_SR_CLNT_HELLO_A ||
182 state == SSL23_ST_SR_CLNT_HELLO_A ||
183 state == SSL23_ST_SR_CLNT_HELLO_B ||
184 state == SSL3_ST_SR_CLNT_HELLO_B ||
185 state == SSL3_ST_SR_CLNT_HELLO_C
186 );
187 }
188
189 void
190 Ssl::ClientBio::stateChanged(const SSL *ssl, int where, int ret)
191 {
192 Ssl::Bio::stateChanged(ssl, where, ret);
193 }
194
195 int
196 Ssl::ClientBio::write(const char *buf, int size, BIO *table)
197 {
198 if (holdWrite_) {
199 BIO_set_retry_write(table);
200 return 0;
201 }
202
203 return Ssl::Bio::write(buf, size, table);
204 }
205
206 const char *objToString(unsigned char const *bytes, int len)
207 {
208 static std::string buf;
209 buf.clear();
210 for (int i = 0; i < len; i++ ) {
211 char tmp[3];
212 snprintf(tmp, sizeof(tmp), "%.2x", bytes[i]);
213 buf.append(tmp);
214 }
215 return buf.c_str();
216 }
217
218 int
219 Ssl::ClientBio::read(char *buf, int size, BIO *table)
220 {
221 if (helloState < atHelloReceived) {
222 int bytes = readAndBuffer(buf, size, table, "TLS client Hello");
223 if (bytes <= 0)
224 return bytes;
225 }
226
227 if (helloState == atHelloNone) {
228 helloSize = receivedHelloFeatures_.parseMsgHead(rbuf);
229 if (helloSize == 0) {
230 // Not enough bytes to get hello message size
231 BIO_set_retry_read(table);
232 return -1;
233 } else if (helloSize < 0) {
234 wrongProtocol = true;
235 return -1;
236 }
237
238 helloState = atHelloStarted; //Next state
239 }
240
241 if (helloState == atHelloStarted) {
242 const unsigned char *head = (const unsigned char *)rbuf.content();
243 const char *s = objToString(head, rbuf.contentSize());
244 debugs(83, 7, "SSL Header: " << s);
245
246 if (helloSize > rbuf.contentSize()) {
247 BIO_set_retry_read(table);
248 return -1;
249 }
250 receivedHelloFeatures_.get(rbuf);
251 helloState = atHelloReceived;
252 }
253
254 if (holdRead_) {
255 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
256 BIO_set_retry_read(table);
257 return -1;
258 }
259
260 if (helloState == atHelloReceived) {
261 if (rbuf.hasContent()) {
262 int bytes = (size <= rbuf.contentSize() ? size : rbuf.contentSize());
263 memcpy(buf, rbuf.content(), bytes);
264 rbuf.consume(bytes);
265 return bytes;
266 } else
267 return Ssl::Bio::read(buf, size, table);
268 }
269
270 return -1;
271 }
272
273 void
274 Ssl::ServerBio::stateChanged(const SSL *ssl, int where, int ret)
275 {
276 Ssl::Bio::stateChanged(ssl, where, ret);
277 }
278
279 void
280 Ssl::ServerBio::setClientFeatures(const Ssl::Bio::sslFeatures &features)
281 {
282 clientFeatures = features;
283 };
284
285 int
286 Ssl::ServerBio::read(char *buf, int size, BIO *table)
287 {
288 return record_ ?
289 readAndBuffer(buf, size, table, "TLS server Hello") : Ssl::Bio::read(buf, size, table);
290 }
291
292 // This function makes the required checks to examine if the client hello
293 // message is compatible with the features provided by OpenSSL toolkit.
294 // If the features are compatible and can be supported it tries to rewrite SSL
295 // structure members, to replace the hello message created by openSSL, with the
296 // web client SSL hello message.
297 // This is mostly possible in the cases where the web client uses openSSL
298 // library similar with this one used by squid.
299 static bool
300 adjustSSL(SSL *ssl, Ssl::Bio::sslFeatures &features)
301 {
302 #if SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK
303 if (!ssl->s3) {
304 debugs(83, 5, "No SSLv3 data found!");
305 return false;
306 }
307
308 // If the client supports compression but our context does not support
309 // we can not adjust.
310 #if !defined(OPENSSL_NO_COMP)
311 const bool requireCompression = (features.compressMethod && ssl->ctx->comp_methods == NULL);
312 #else
313 const bool requireCompression = features.compressMethod;
314 #endif
315 if (requireCompression) {
316 debugs(83, 5, "Client Hello Data supports compression, but we do not!");
317 return false;
318 }
319
320 // Check ciphers list
321 size_t token = 0;
322 size_t end = 0;
323 while (token != std::string::npos) {
324 end = features.clientRequestedCiphers.find(':',token);
325 std::string cipher;
326 cipher.assign(features.clientRequestedCiphers, token, end - token);
327 token = (end != std::string::npos ? end + 1 : std::string::npos);
328 bool found = false;
329 STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(ssl);
330 for (int i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) {
331 SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
332 const char *cname = SSL_CIPHER_get_name(c);
333 if (cipher.compare(cname)) {
334 found = true;
335 break;
336 }
337 }
338 if (!found) {
339 debugs(83, 5, "Client Hello Data supports cipher '"<< cipher <<"' but we do not support it!");
340 return false;
341 }
342 }
343
344 #if !defined(SSL_TLSEXT_HB_ENABLED)
345 if (features.doHeartBeats) {
346 debugs(83, 5, "Client Hello Data supports HeartBeats but we do not support!");
347 return false;
348 }
349 #endif
350
351 for (std::list<int>::iterator it = features.extensions.begin(); it != features.extensions.end(); ++it) {
352 static int supportedExtensions[] = {
353 #if defined(TLSEXT_TYPE_server_name)
354 TLSEXT_TYPE_server_name,
355 #endif
356 #if defined(TLSEXT_TYPE_opaque_prf_input)
357 TLSEXT_TYPE_opaque_prf_input,
358 #endif
359 #if defined(TLSEXT_TYPE_heartbeat)
360 TLSEXT_TYPE_heartbeat,
361 #endif
362 #if defined(TLSEXT_TYPE_renegotiate)
363 TLSEXT_TYPE_renegotiate,
364 #endif
365 #if defined(TLSEXT_TYPE_ec_point_formats)
366 TLSEXT_TYPE_ec_point_formats,
367 #endif
368 #if defined(TLSEXT_TYPE_elliptic_curves)
369 TLSEXT_TYPE_elliptic_curves,
370 #endif
371 #if defined(TLSEXT_TYPE_session_ticket)
372 TLSEXT_TYPE_session_ticket,
373 #endif
374 #if defined(TLSEXT_TYPE_status_request)
375 TLSEXT_TYPE_status_request,
376 #endif
377 #if defined(TLSEXT_TYPE_use_srtp)
378 TLSEXT_TYPE_use_srtp,
379 #endif
380 #if 0 //Allow 13172 Firefox supported extension for testing purposes
381 13172,
382 #endif
383 -1
384 };
385 bool found = false;
386 for (int i = 0; supportedExtensions[i] != -1; i++) {
387 if (*it == supportedExtensions[i]) {
388 found = true;
389 break;
390 }
391 }
392 if (!found) {
393 debugs(83, 5, "Extension " << *it << " does not supported!");
394 return false;
395 }
396 }
397
398 SSL3_BUFFER *wb=&(ssl->s3->wbuf);
399 if (wb->len < (size_t)features.helloMessage.length())
400 return false;
401
402 debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
403
404 //Adjust ssl structure data.
405 // We need to fix the random in SSL struct:
406 memcpy(ssl->s3->client_random, features.client_random, SSL3_RANDOM_SIZE);
407 memcpy(wb->buf, features.helloMessage.rawContent(), features.helloMessage.length());
408 wb->left = features.helloMessage.length();
409
410 size_t mainHelloSize = features.helloMessage.length() - 5;
411 const char *mainHello = features.helloMessage.rawContent() + 5;
412 assert((size_t)ssl->init_buf->max > mainHelloSize);
413 memcpy(ssl->init_buf->data, mainHello, mainHelloSize);
414 debugs(83, 5, "Hello Data init and adjustd sizes :" << ssl->init_num << " = "<< mainHelloSize);
415 ssl->init_num = mainHelloSize;
416 ssl->s3->wpend_ret = mainHelloSize;
417 ssl->s3->wpend_tot = mainHelloSize;
418 return true;
419 #else
420 return false;
421 #endif
422 }
423
424 int
425 Ssl::ServerBio::write(const char *buf, int size, BIO *table)
426 {
427
428 if (holdWrite_) {
429 debugs(83, 7, "Hold write, for SSL connection on " << fd_ << "will not write bytes of size " << size);
430 BIO_set_retry_write(table);
431 return -1;
432 }
433
434 if (!helloBuild && (bumpMode_ == Ssl::bumpPeek || bumpMode_ == Ssl::bumpStare)) {
435 if (
436 buf[1] >= 3 //it is an SSL Version3 message
437 && buf[0] == 0x16 // and it is a Handshake/Hello message
438 ) {
439
440 //Hello message is the first message we write to server
441 assert(helloMsg.isEmpty());
442
443 auto ssl = fd_table[fd_].ssl.get();
444 if (clientFeatures.initialized_ && ssl) {
445 if (bumpMode_ == Ssl::bumpPeek) {
446 if (adjustSSL(ssl, clientFeatures))
447 allowBump = true;
448 allowSplice = true;
449 helloMsg.append(clientFeatures.helloMessage);
450 debugs(83, 7, "SSL HELLO message for FD " << fd_ << ": Random number is adjusted for peek mode");
451 } else { /*Ssl::bumpStare*/
452 allowBump = true;
453 if (adjustSSL(ssl, clientFeatures)) {
454 allowSplice = true;
455 helloMsg.append(clientFeatures.helloMessage);
456 debugs(83, 7, "SSL HELLO message for FD " << fd_ << ": Random number is adjusted for stare mode");
457 }
458 }
459 }
460 }
461 // If we do not build any hello message, copy the current
462 if (helloMsg.isEmpty())
463 helloMsg.append(buf, size);
464
465 helloBuild = true;
466 helloMsgSize = helloMsg.length();
467 //allowBump = true;
468
469 if (allowSplice) {
470 // Do not write yet.....
471 BIO_set_retry_write(table);
472 return -1;
473 }
474 }
475
476 if (!helloMsg.isEmpty()) {
477 debugs(83, 7, "buffered write for FD " << fd_);
478 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
479 helloMsg.consume(ret);
480 if (!helloMsg.isEmpty()) {
481 // We need to retry sendind data.
482 // Say to openSSL to retry sending hello message
483 BIO_set_retry_write(table);
484 return -1;
485 }
486
487 // Sending hello message complete. Do not send more data for now...
488 holdWrite_ = true;
489
490 // spoof openSSL that we write what it ask us to write
491 return size;
492 } else
493 return Ssl::Bio::write(buf, size, table);
494 }
495
496 void
497 Ssl::ServerBio::flush(BIO *table)
498 {
499 if (!helloMsg.isEmpty()) {
500 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
501 helloMsg.consume(ret);
502 }
503 }
504
505 void
506 Ssl::ServerBio::extractHelloFeatures()
507 {
508 if (!receivedHelloFeatures_.initialized_)
509 receivedHelloFeatures_.get(rbuf, false);
510 }
511
512 bool
513 Ssl::ServerBio::resumingSession()
514 {
515 extractHelloFeatures();
516
517 if (!clientFeatures.sessionId.isEmpty() && !receivedHelloFeatures_.sessionId.isEmpty())
518 return clientFeatures.sessionId == receivedHelloFeatures_.sessionId;
519
520 // is this a session resuming attempt using TLS tickets?
521 if (clientFeatures.hasTlsTicket &&
522 receivedHelloFeatures_.tlsTicketsExtension &&
523 receivedHelloFeatures_.hasCcsOrNst)
524 return true;
525
526 return false;
527 }
528
529 /// initializes BIO table after allocation
530 static int
531 squid_bio_create(BIO *bi)
532 {
533 bi->init = 0; // set when we store Bio object and socket fd (BIO_C_SET_FD)
534 bi->num = 0;
535 bi->ptr = NULL;
536 bi->flags = 0;
537 return 1;
538 }
539
540 /// cleans BIO table before deallocation
541 static int
542 squid_bio_destroy(BIO *table)
543 {
544 delete static_cast<Ssl::Bio*>(table->ptr);
545 table->ptr = NULL;
546 return 1;
547 }
548
549 /// wrapper for Bio::write()
550 static int
551 squid_bio_write(BIO *table, const char *buf, int size)
552 {
553 Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr);
554 assert(bio);
555 return bio->write(buf, size, table);
556 }
557
558 /// wrapper for Bio::read()
559 static int
560 squid_bio_read(BIO *table, char *buf, int size)
561 {
562 Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr);
563 assert(bio);
564 return bio->read(buf, size, table);
565 }
566
567 /// implements puts() via write()
568 static int
569 squid_bio_puts(BIO *table, const char *str)
570 {
571 assert(str);
572 return squid_bio_write(table, str, strlen(str));
573 }
574
575 /// other BIO manipulations (those without dedicated callbacks in BIO table)
576 static long
577 squid_bio_ctrl(BIO *table, int cmd, long arg1, void *arg2)
578 {
579 debugs(83, 5, table << ' ' << cmd << '(' << arg1 << ", " << arg2 << ')');
580
581 switch (cmd) {
582 case BIO_C_SET_FD: {
583 assert(arg2);
584 const int fd = *static_cast<int*>(arg2);
585 Ssl::Bio *bio;
586 if (arg1 == Ssl::Bio::BIO_TO_SERVER)
587 bio = new Ssl::ServerBio(fd);
588 else
589 bio = new Ssl::ClientBio(fd);
590 assert(!table->ptr);
591 table->ptr = bio;
592 table->init = 1;
593 return 0;
594 }
595
596 case BIO_C_GET_FD:
597 if (table->init) {
598 Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr);
599 assert(bio);
600 if (arg2)
601 *static_cast<int*>(arg2) = bio->fd();
602 return bio->fd();
603 }
604 return -1;
605
606 case BIO_CTRL_DUP:
607 // Should implemented if the SSL_dup openSSL API function
608 // used anywhere in squid.
609 return 0;
610
611 case BIO_CTRL_FLUSH:
612 if (table->init) {
613 Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr);
614 assert(bio);
615 bio->flush(table);
616 return 1;
617 }
618 return 0;
619
620 /* we may also need to implement these:
621 case BIO_CTRL_RESET:
622 case BIO_C_FILE_SEEK:
623 case BIO_C_FILE_TELL:
624 case BIO_CTRL_INFO:
625 case BIO_CTRL_GET_CLOSE:
626 case BIO_CTRL_SET_CLOSE:
627 case BIO_CTRL_PENDING:
628 case BIO_CTRL_WPENDING:
629 */
630 default:
631 return 0;
632
633 }
634
635 return 0; /* NOTREACHED */
636 }
637
638 /// wrapper for Bio::stateChanged()
639 static void
640 squid_ssl_info(const SSL *ssl, int where, int ret)
641 {
642 if (BIO *table = SSL_get_rbio(ssl)) {
643 if (Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr))
644 bio->stateChanged(ssl, where, ret);
645 }
646 }
647
648 Ssl::Bio::sslFeatures::sslFeatures():
649 sslHelloVersion(-1),
650 sslVersion(-1),
651 compressMethod(-1),
652 helloMsgSize(0),
653 unknownCiphers(false),
654 doHeartBeats(true),
655 tlsTicketsExtension(false),
656 hasTlsTicket(false),
657 tlsStatusRequest(false),
658 hasCcsOrNst(false),
659 initialized_(false)
660 {
661 memset(client_random, 0, SSL3_RANDOM_SIZE);
662 }
663
664 int Ssl::Bio::sslFeatures::toSquidSSLVersion() const
665 {
666 if (sslVersion == SSL2_VERSION)
667 return 2;
668 else if (sslVersion == SSL3_VERSION)
669 return 3;
670 else if (sslVersion == TLS1_VERSION)
671 return 4;
672 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
673 else if (sslVersion == TLS1_1_VERSION)
674 return 5;
675 else if (sslVersion == TLS1_2_VERSION)
676 return 6;
677 #endif
678 else
679 return 1;
680 }
681
682 bool
683 Ssl::Bio::sslFeatures::get(const SSL *ssl)
684 {
685 sslVersion = SSL_version(ssl);
686 debugs(83, 7, "SSL version: " << SSL_get_version(ssl) << " (" << sslVersion << ")");
687
688 #if defined(TLSEXT_NAMETYPE_host_name)
689 if (const char *server = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))
690 serverName = server;
691 debugs(83, 7, "SNI server name: " << serverName);
692 #endif
693
694 #if !defined(OPENSSL_NO_COMP)
695 if (ssl->session->compress_meth)
696 compressMethod = ssl->session->compress_meth;
697 else if (sslVersion >= 3) //if it is 3 or newer version then compression is disabled
698 #endif
699 compressMethod = 0;
700 debugs(83, 7, "SSL compression: " << compressMethod);
701
702 STACK_OF(SSL_CIPHER) * ciphers = NULL;
703 if (ssl->server)
704 ciphers = ssl->session->ciphers;
705 else
706 ciphers = ssl->cipher_list;
707 if (ciphers) {
708 for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) {
709 SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i);
710 if (c != NULL) {
711 if (!clientRequestedCiphers.empty())
712 clientRequestedCiphers.append(":");
713 clientRequestedCiphers.append(c->name);
714 }
715 }
716 }
717 debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers);
718
719 if (sslVersion >=3 && ssl->s3 && ssl->s3->client_random[0]) {
720 memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE);
721 }
722
723 #if 0 /* XXX: OpenSSL 0.9.8k lacks at least some of these tlsext_* fields */
724 //The following extracted for logging purpuses:
725 // TLSEXT_TYPE_ec_point_formats
726 unsigned char *p;
727 int len;
728 if (ssl->server) {
729 p = ssl->session->tlsext_ecpointformatlist;
730 len = ssl->session->tlsext_ecpointformatlist_length;
731 } else {
732 p = ssl->tlsext_ecpointformatlist;
733 len = ssl->tlsext_ecpointformatlist_length;
734 }
735 if (p) {
736 ecPointFormatList = objToString(p, len);
737 debugs(83, 7, "tlsExtension ecPointFormatList of length " << len << " :" << ecPointFormatList);
738 }
739
740 // TLSEXT_TYPE_elliptic_curves
741 if (ssl->server) {
742 p = ssl->session->tlsext_ellipticcurvelist;
743 len = ssl->session->tlsext_ellipticcurvelist_length;
744 } else {
745 p = ssl->tlsext_ellipticcurvelist;
746 len = ssl->tlsext_ellipticcurvelist_length;
747 }
748 if (p) {
749 ellipticCurves = objToString(p, len);
750 debugs(83, 7, "tlsExtension ellipticCurveList of length " << len <<" :" << ellipticCurves);
751 }
752 // TLSEXT_TYPE_opaque_prf_input
753 p = NULL;
754 if (ssl->server) {
755 if (ssl->s3 && ssl->s3->client_opaque_prf_input) {
756 p = (unsigned char *)ssl->s3->client_opaque_prf_input;
757 len = ssl->s3->client_opaque_prf_input_len;
758 }
759 } else {
760 p = (unsigned char *)ssl->tlsext_opaque_prf_input;
761 len = ssl->tlsext_opaque_prf_input_len;
762 }
763 if (p) {
764 debugs(83, 7, "tlsExtension client-opaque-prf-input of length " << len);
765 opaquePrf = objToString(p, len);
766 }
767 #endif
768 initialized_ = true;
769 return true;
770 }
771
772 int
773 Ssl::Bio::sslFeatures::parseMsgHead(const MemBuf &buf)
774 {
775 const unsigned char *head = (const unsigned char *)buf.content();
776 const char *s = objToString(head, buf.contentSize());
777 debugs(83, 7, "SSL Header: " << s);
778 if (buf.contentSize() < 5)
779 return 0;
780
781 if (helloMsgSize > 0)
782 return helloMsgSize;
783
784 // Check for SSLPlaintext/TLSPlaintext record
785 // RFC6101 section 5.2.1
786 // RFC5246 section 6.2.1
787 if (head[0] == 0x16) {
788 debugs(83, 7, "SSL version 3 handshake message");
789 // The SSL version exist in the 2nd and 3rd bytes
790 sslHelloVersion = (head[1] << 8) | head[2];
791 debugs(83, 7, "SSL Version :" << std::hex << std::setw(8) << std::setfill('0') << sslVersion);
792 // The hello message size exist in 4th and 5th bytes
793 helloMsgSize = (head[3] << 8) + head[4];
794 debugs(83, 7, "SSL Header Size: " << helloMsgSize);
795 helloMsgSize +=5;
796 } else if ((head[0] & 0x80) && head[2] == 0x01 && head[3] == 0x03) {
797 debugs(83, 7, "SSL version 2 handshake message with v3 support");
798 sslHelloVersion = 0x0002;
799 debugs(83, 7, "SSL Version :" << std::hex << std::setw(8) << std::setfill('0') << sslVersion);
800 // The hello message size exist in 2nd byte
801 helloMsgSize = head[1];
802 helloMsgSize +=2;
803 } else {
804 debugs(83, 7, "Not an SSL acceptable handshake message (SSLv2 message?)");
805 return (helloMsgSize = -1);
806 }
807
808 // Set object as initialized. Even if we did not full parsing yet
809 // The basic features, like the SSL version is set
810 initialized_ = true;
811 return helloMsgSize;
812 }
813
814 bool
815 Ssl::Bio::sslFeatures::checkForCcsOrNst(const unsigned char *msg, size_t size)
816 {
817 while (size > 5) {
818 const int msgType = msg[0];
819 const int msgSslVersion = (msg[1] << 8) | msg[2];
820 debugs(83, 7, "SSL Message Version :" << std::hex << std::setw(8) << std::setfill('0') << msgSslVersion);
821 // Check for Change Cipher Spec message
822 // RFC5246 section 6.2.1
823 if (msgType == 0x14) {// Change Cipher Spec message found
824 debugs(83, 7, "SSL Change Cipher Spec message found");
825 return true;
826 }
827 // Check for New Session Ticket message
828 // RFC5077 section 3.3
829 if (msgType == 0x04) {// New Session Ticket message found
830 debugs(83, 7, "TLS New Session Ticket message found");
831 return true;
832 }
833 // The hello message size exist in 4th and 5th bytes
834 size_t msgLength = (msg[3] << 8) + msg[4];
835 debugs(83, 7, "SSL Message Size: " << msgLength);
836 msgLength += 5;
837
838 if (msgLength <= size) {
839 msg += msgLength;
840 size -= msgLength;
841 } else
842 size = 0;
843 }
844 return false;
845 }
846
847 bool
848 Ssl::Bio::sslFeatures::get(const MemBuf &buf, bool record)
849 {
850 int msgSize;
851 if ((msgSize = parseMsgHead(buf)) <= 0) {
852 debugs(83, 7, "Not a known SSL handshake message");
853 return false;
854 }
855
856 if (msgSize > buf.contentSize()) {
857 debugs(83, 2, "Partial SSL handshake message, can not parse!");
858 return false;
859 }
860
861 if (record) {
862 helloMessage.clear();
863 helloMessage.append(buf.content(), buf.contentSize());
864 }
865
866 const unsigned char *msg = (const unsigned char *)buf.content();
867 if (msg[0] & 0x80)
868 return parseV23Hello(msg, (size_t)msgSize);
869 else {
870 // Hello messages require 5 bytes header + 1 byte Msg type + 3 bytes for Msg size
871 if (buf.contentSize() < 9)
872 return false;
873
874 // Check for the Handshake/Message type
875 // The type 2 is a ServerHello, the type 1 is a ClientHello
876 // RFC5246 section 7.4
877 if (msg[5] == 0x2) { // ServerHello message
878 if (parseV3ServerHello(msg, (size_t)msgSize)) {
879 hasCcsOrNst = checkForCcsOrNst(msg + msgSize, buf.contentSize() - msgSize);
880 return true;
881 }
882 } else if (msg[5] == 0x1) // ClientHello message,
883 return parseV3Hello(msg, (size_t)msgSize);
884 }
885
886 return false;
887 }
888
889 bool
890 Ssl::Bio::sslFeatures::parseV3ServerHello(const unsigned char *messageContainer, size_t messageContainerSize)
891 {
892 // Parse a ServerHello Handshake message
893 // RFC5246 section 7.4, 7.4.1.3
894 // The ServerHello starts at messageContainer + 5
895 const unsigned char *serverHello = messageContainer + 5;
896
897 // The Length field (bytes 1-3) plus 4 bytes of the serverHello message header (1 handshake type + 3 hello length)
898 const size_t helloSize = ((serverHello[1] << 16) | (serverHello[2] << 8) | serverHello[3]) + 4;
899 debugs(83, 7, "ServerHello message size: " << helloSize);
900 if (helloSize > messageContainerSize) {
901 debugs(83, 2, "ServerHello parse error");
902 return false;
903 }
904
905 // helloSize should be at least 38 bytes long:
906 // (SSL Version + Random + SessionId Length + Cipher Suite + Compression Method)
907 if (helloSize < 38) {
908 debugs(83, 2, "Too short ServerHello message");
909 return false;
910 }
911
912 debugs(83, 7, "Get fake features from v3 ServerHello message.");
913 // Get the correct version of the sub-hello message
914 sslVersion = (serverHello[4] << 8) | serverHello[5];
915 // At the position 38 (HelloHeader (6bytes) + SSL3_RANDOM_SIZE (32bytes))
916 const size_t sessIdLen = static_cast<size_t>(serverHello[38]);
917 debugs(83, 7, "Session ID Length: " << sessIdLen);
918
919 // The size should be enough to hold at least the following
920 // 4 (hello header)
921 // + 2 (SSL Version) + 32 (random) + 1 (sessionId length)
922 // + sessIdLength + 2 (cipher suite) + 1 (compression method)
923 // = 42 + sessIdLength
924 if (42 + sessIdLen > helloSize) {
925 debugs(83, 2, "ciphers length parse error");
926 return false;
927 }
928
929 // The sessionID stored at 39 position, after sessionID length field
930 sessionId.assign(reinterpret_cast<const char *>(serverHello + 39), sessIdLen);
931
932 // Check if there are extensions in hello message
933 // RFC5246 section 7.4.1.4
934 if (helloSize > 42 + sessIdLen + 2) {
935 // 42 + sessIdLen
936 const unsigned char *pToExtensions = serverHello + 42 + sessIdLen;
937 const size_t extensionsLen = (pToExtensions[0] << 8) | pToExtensions[1];
938 // Check if the hello size can hold extensions
939 if (42 + 2 + sessIdLen + extensionsLen > helloSize ) {
940 debugs(83, 2, "Extensions length parse error");
941 return false;
942 }
943
944 pToExtensions += 2;
945 const unsigned char *ext = pToExtensions;
946 while (ext + 4 <= pToExtensions + extensionsLen) {
947 const size_t extType = (ext[0] << 8) | ext[1];
948 ext += 2;
949 const size_t extLen = (ext[0] << 8) | ext[1];
950 ext += 2;
951 debugs(83, 7, "TLS Extension: " << std::hex << extType << " of size:" << extLen);
952 // SessionTicket TLS Extension, RFC5077 section 3.2
953 if (extType == 0x23) {
954 tlsTicketsExtension = true;
955 }
956 ext += extLen;
957 }
958 }
959 return true;
960 }
961
962 bool
963 Ssl::Bio::sslFeatures::parseV3Hello(const unsigned char *messageContainer, size_t messageContainerSize)
964 {
965 // Parse a ClientHello Handshake message
966 // RFC5246 section 7.4, 7.4.1.2
967 // The ClientHello starts at messageContainer + 5
968 const unsigned char * clientHello = messageContainer + 5;
969
970 debugs(83, 7, "Get fake features from v3 ClientHello message.");
971 // The Length field (bytes 1-3) plus 4 bytes of the clientHello message header (1 handshake type + 3 hello length)
972 const size_t helloSize = ((clientHello[1] << 16) | (clientHello[2] << 8) | clientHello[3]) + 4;
973 debugs(83, 7, "ClientHello message size: " << helloSize);
974 if (helloSize > messageContainerSize) {
975 debugs(83, 2, "ClientHello parse error");
976 return false;
977 }
978
979 // helloSize should be at least 38 bytes long:
980 // (SSL Version(2) + Random(32) + SessionId Length(1) + Cipher Suite Length(2) + Compression Method Length(1))
981 if (helloSize < 38) {
982 debugs(83, 2, "Too short ClientHello message");
983 return false;
984 }
985
986 //For SSLv3 or TLSv1.* protocols we can get some more informations
987 if (messageContainer[1] != 0x3 || clientHello[0] != 0x1 /*HELLO A message*/) {
988 debugs(83, 2, "Not an SSLv3/TLSv1.x client hello message, stop parsing here");
989 return true;
990 }
991
992 // Get the correct version of the sub-hello message
993 sslVersion = (clientHello[4] << 8) | clientHello[5];
994 //Get Client Random number. It starts on the position 6 of clientHello message
995 memcpy(client_random, clientHello + 6, SSL3_RANDOM_SIZE);
996 debugs(83, 7, "Client random: " << objToString(client_random, SSL3_RANDOM_SIZE));
997
998 // At the position 38 (6+SSL3_RANDOM_SIZE)
999 const size_t sessIDLen = static_cast<size_t>(clientHello[38]);
1000 debugs(83, 7, "Session ID Length: " << sessIDLen);
1001
1002 // The helloSize should be enough to hold at least the following
1003 // 1 handshake type + 3 hello Length
1004 // + 2 (SSL Version) + 32 (random) + 1 (sessionId length)
1005 // + sessIdLength + 2 (cipher suite length) + 1 (compression method length)
1006 // = 42 + sessIdLength
1007 if (42 + sessIDLen > helloSize) {
1008 debugs(83, 2, "Session ID length parse error");
1009 return false;
1010 }
1011
1012 // The sessionID stored art 39 position, after sessionID length field
1013 sessionId.assign(reinterpret_cast<const char *>(clientHello + 39), sessIDLen);
1014
1015 //Ciphers list. It is stored after the Session ID.
1016 // It is a variable-length vector(RFC5246 section 4.3)
1017 const unsigned char *ciphers = clientHello + 39 + sessIDLen;
1018 const size_t ciphersLen = (ciphers[0] << 8) | ciphers[1];
1019 if (42 + sessIDLen + ciphersLen > helloSize) {
1020 debugs(83, 2, "ciphers length parse error");
1021 return false;
1022 }
1023
1024 ciphers += 2;
1025 if (ciphersLen) {
1026 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
1027 const SSL_METHOD *method = TLS_method();
1028 #else
1029 const SSL_METHOD *method = SSLv23_method();
1030 #endif
1031 for (size_t i = 0; i < ciphersLen; i += 2) {
1032 // each cipher in v3/tls HELLO message is of size 2
1033 const SSL_CIPHER *c = method->get_cipher_by_char((ciphers + i));
1034 if (c != NULL) {
1035 if (!clientRequestedCiphers.empty())
1036 clientRequestedCiphers.append(":");
1037 clientRequestedCiphers.append(c->name);
1038 } else
1039 unknownCiphers = true;
1040 }
1041 }
1042 debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers);
1043
1044 // Compression field: 1 bytes the number of compression methods and
1045 // 1 byte for each compression method
1046 const unsigned char *compression = ciphers + ciphersLen;
1047 if (compression[0] > 1)
1048 compressMethod = 1;
1049 else
1050 compressMethod = 0;
1051 debugs(83, 7, "SSL compression methods number: " << static_cast<int>(compression[0]));
1052
1053 // Parse Extensions, RFC5246 section 7.4.1.4
1054 const unsigned char *pToExtensions = compression + 1 + static_cast<int>(compression[0]);
1055 if ((size_t)((pToExtensions - clientHello) + 2) < helloSize) {
1056 const size_t extensionsLen = (pToExtensions[0] << 8) | pToExtensions[1];
1057 if ((pToExtensions - clientHello) + 2 + extensionsLen > helloSize) {
1058 debugs(83, 2, "Extensions length parse error");
1059 return false;
1060 }
1061
1062 pToExtensions += 2;
1063 const unsigned char *ext = pToExtensions;
1064 while (ext + 4 <= pToExtensions + extensionsLen) {
1065 const size_t extType = (ext[0] << 8) | ext[1];
1066 ext += 2;
1067 const size_t extLen = (ext[0] << 8) | ext[1];
1068 ext += 2;
1069 debugs(83, 7, "TLS Extension: " << std::hex << extType << " of size:" << extLen);
1070
1071 if (ext + extLen > pToExtensions + extensionsLen) {
1072 debugs(83, 2, "Extension " << std::hex << extType << " length parser error");
1073 return false;
1074 }
1075
1076 //The SNI extension has the type 0 (extType == 0)
1077 // RFC6066 sections 3, 10.2
1078 // The two first bytes indicates the length of the SNI data (should be extLen-2)
1079 // The next byte is the hostname type, it should be '0' for normal hostname (ext[2] == 0)
1080 // The 3rd and 4th bytes are the length of the hostname
1081 if (extType == 0 && ext[2] == 0) {
1082 const size_t hostLen = (ext[3] << 8) | ext[4];
1083 if (hostLen < extLen)
1084 serverName.assign(reinterpret_cast<const char *>(ext+5), hostLen);
1085 debugs(83, 7, "Found server name: " << serverName);
1086 } else if (extType == 15 && ext[0] != 0) {
1087 // The heartBeats are the type 15, RFC6520
1088 doHeartBeats = true;
1089 } else if (extType == 0x23) {
1090 //SessionTicket TLS Extension RFC5077
1091 tlsTicketsExtension = true;
1092 if (extLen != 0)
1093 hasTlsTicket = true;
1094 } else if (extType == 0x05) {
1095 // RFC6066 sections 8, 10.2
1096 tlsStatusRequest = true;
1097 } else if (extType == 0x3374) {
1098 // detected TLS next protocol negotiate extension
1099 } else if (extType == 0x10) {
1100 // Application-Layer Protocol Negotiation Extension, RFC7301
1101 const size_t listLen = (ext[0] << 8) | ext[1];
1102 if (listLen < extLen)
1103 tlsAppLayerProtoNeg.assign(reinterpret_cast<const char *>(ext+5), listLen);
1104 } else
1105 extensions.push_back(extType);
1106
1107 ext += extLen;
1108 }
1109 }
1110 return true;
1111 }
1112
1113 bool
1114 Ssl::Bio::sslFeatures::parseV23Hello(const unsigned char *hello, size_t size)
1115 {
1116 debugs(83, 7, "Get fake features from v23 ClientHello message.");
1117 if (size < 7)
1118 return false;
1119
1120 // Get the SSL/TLS version supported by client
1121 sslVersion = (hello[3] << 8) | hello[4];
1122
1123 //Ciphers list. It is stored after the Session ID.
1124 const unsigned int ciphersLen = (hello[5] << 8) | hello[6];
1125 const unsigned char *ciphers = hello + 11;
1126
1127 if (size < ciphersLen + 11)
1128 return false;
1129
1130 if (ciphersLen) {
1131 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
1132 const SSL_METHOD *method = TLS_method();
1133 #else
1134 const SSL_METHOD *method = SSLv23_method();
1135 #endif
1136 for (unsigned int i = 0; i < ciphersLen; i += 3) {
1137 // The v2 hello messages cipher has 3 bytes.
1138 // The v2 cipher has the first byte not null
1139 // Because we are going to sent only v3 message we
1140 // are ignoring these ciphers
1141 if (ciphers[i] != 0)
1142 continue;
1143 const SSL_CIPHER *c = method->get_cipher_by_char((ciphers + i + 1));
1144 if (c != NULL) {
1145 if (!clientRequestedCiphers.empty())
1146 clientRequestedCiphers.append(":");
1147 clientRequestedCiphers.append(c->name);
1148 }
1149 }
1150 }
1151 debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers);
1152
1153 const unsigned int sessionIdLength = (hello[7] << 8) | hello[8];
1154 debugs(83, 7, "SessionID length: " << sessionIdLength);
1155 // SessionID starts at: hello+11+ciphersLen
1156 if (sessionIdLength)
1157 sessionId.assign((const char *)(hello + 11 + ciphersLen), sessionIdLength);
1158
1159 const unsigned int challengeLength = (hello[5] << 9) | hello[10];
1160 debugs(83, 7, "Challenge Length: " << challengeLength);
1161 //challenge starts at: hello+11+ciphersLen+sessionIdLength
1162
1163 compressMethod = 0;
1164 return true;
1165 }
1166
1167 void
1168 Ssl::Bio::sslFeatures::applyToSSL(SSL *ssl, Ssl::BumpMode bumpMode) const
1169 {
1170 // To increase the possibility for bumping after peek mode selection or
1171 // splicing after stare mode selection it is good to set the
1172 // SSL protocol version.
1173 // The SSL_set_ssl_method is not the correct method because it will strict
1174 // SSL version which can be used to the SSL version used for client hello message.
1175 // For example will prevent comunnicating with a tls1.0 server if the
1176 // client sent and tlsv1.2 Hello message.
1177 #if defined(TLSEXT_NAMETYPE_host_name)
1178 if (!serverName.isEmpty()) {
1179 SSL_set_tlsext_host_name(ssl, serverName.c_str());
1180 }
1181 #endif
1182 if (!clientRequestedCiphers.empty())
1183 SSL_set_cipher_list(ssl, clientRequestedCiphers.c_str());
1184 #if defined(SSL_OP_NO_COMPRESSION) /* XXX: OpenSSL 0.9.8k lacks SSL_OP_NO_COMPRESSION */
1185 if (compressMethod == 0)
1186 SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
1187 #endif
1188
1189 #if defined(TLSEXT_STATUSTYPE_ocsp)
1190 if (tlsStatusRequest)
1191 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
1192 #endif
1193
1194 #if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
1195 if (!tlsAppLayerProtoNeg.isEmpty()) {
1196 if (bumpMode == Ssl::bumpPeek)
1197 SSL_set_alpn_protos(ssl, (const unsigned char*)tlsAppLayerProtoNeg.rawContent(), tlsAppLayerProtoNeg.length());
1198 else {
1199 static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
1200 SSL_set_alpn_protos(ssl, supported_protos, sizeof(supported_protos));
1201 }
1202 }
1203 #endif
1204 }
1205
1206 std::ostream &
1207 Ssl::Bio::sslFeatures::print(std::ostream &os) const
1208 {
1209 static std::string buf;
1210 // TODO: Also print missing features like the HeartBeats and AppLayerProtoNeg
1211 return os << "v" << sslVersion <<
1212 " SNI:" << (serverName.isEmpty() ? SBuf("-") : serverName) <<
1213 " comp:" << compressMethod <<
1214 " Ciphers:" << clientRequestedCiphers <<
1215 " Random:" << objToString(client_random, SSL3_RANDOM_SIZE) <<
1216 " ecPointFormats:" << ecPointFormatList <<
1217 " ec:" << ellipticCurves <<
1218 " opaquePrf:" << opaquePrf;
1219 }
1220
1221 #endif /* USE_SSL */
1222