]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/bio.cc
SSLv2 records force SslBump bumping despite a matching step2 peek rule.
[thirdparty/squid.git] / src / ssl / bio.cc
1 /*
2 * Copyright (C) 1996-2017 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 "fd.h"
19 #include "fde.h"
20 #include "globals.h"
21 #include "ip/Address.h"
22 #include "parser/BinaryTokenizer.h"
23 #include "SquidTime.h"
24 #include "ssl/bio.h"
25
26 #if HAVE_OPENSSL_SSL_H
27 #include <openssl/ssl.h>
28 #endif
29
30 #if _SQUID_WINDOWS_
31 extern int socket_read_method(int, char *, int);
32 extern int socket_write_method(int, const char *, int);
33 #endif
34
35 /* BIO callbacks */
36 static int squid_bio_write(BIO *h, const char *buf, int num);
37 static int squid_bio_read(BIO *h, char *buf, int size);
38 static int squid_bio_puts(BIO *h, const char *str);
39 //static int squid_bio_gets(BIO *h, char *str, int size);
40 static long squid_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
41 static int squid_bio_create(BIO *h);
42 static int squid_bio_destroy(BIO *data);
43 /* SSL callbacks */
44 static void squid_ssl_info(const SSL *ssl, int where, int ret);
45
46 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
47 /// Initialization structure for the BIO table with
48 /// Squid-specific methods and BIO method wrappers.
49 static BIO_METHOD SquidMethods = {
50 BIO_TYPE_SOCKET,
51 "squid",
52 squid_bio_write,
53 squid_bio_read,
54 squid_bio_puts,
55 NULL, // squid_bio_gets not supported
56 squid_bio_ctrl,
57 squid_bio_create,
58 squid_bio_destroy,
59 NULL // squid_callback_ctrl not supported
60 };
61 #else
62 static BIO_METHOD *SquidMethods = NULL;
63 #endif
64
65 BIO *
66 Ssl::Bio::Create(const int fd, Ssl::Bio::Type type)
67 {
68 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
69 BIO_METHOD *useMethod = &SquidMethods;
70 #else
71 if (!SquidMethods) {
72 SquidMethods = BIO_meth_new(BIO_TYPE_SOCKET, "squid");
73 BIO_meth_set_write(SquidMethods, squid_bio_write);
74 BIO_meth_set_read(SquidMethods, squid_bio_read);
75 BIO_meth_set_puts(SquidMethods, squid_bio_puts);
76 BIO_meth_set_gets(SquidMethods, NULL);
77 BIO_meth_set_ctrl(SquidMethods, squid_bio_ctrl);
78 BIO_meth_set_create(SquidMethods, squid_bio_create);
79 BIO_meth_set_destroy(SquidMethods, squid_bio_destroy);
80 }
81 const BIO_METHOD *useMethod = SquidMethods;
82 #endif
83
84 if (BIO *bio = BIO_new(useMethod)) {
85 BIO_int_ctrl(bio, BIO_C_SET_FD, type, fd);
86 return bio;
87 }
88 return NULL;
89 }
90
91 void
92 Ssl::Bio::Link(SSL *ssl, BIO *bio)
93 {
94 SSL_set_bio(ssl, bio, bio); // cannot fail
95 SSL_set_info_callback(ssl, &squid_ssl_info); // does not provide diagnostic
96 }
97
98 Ssl::Bio::Bio(const int anFd): fd_(anFd)
99 {
100 debugs(83, 7, "Bio constructed, this=" << this << " FD " << fd_);
101 }
102
103 Ssl::Bio::~Bio()
104 {
105 debugs(83, 7, "Bio destructing, this=" << this << " FD " << fd_);
106 }
107
108 int Ssl::Bio::write(const char *buf, int size, BIO *table)
109 {
110 errno = 0;
111 #if _SQUID_WINDOWS_
112 const int result = socket_write_method(fd_, buf, size);
113 #else
114 const int result = default_write_method(fd_, buf, size);
115 #endif
116 const int xerrno = errno;
117 debugs(83, 5, "FD " << fd_ << " wrote " << 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_write(table);
125 }
126
127 return result;
128 }
129
130 int
131 Ssl::Bio::read(char *buf, int size, BIO *table)
132 {
133 errno = 0;
134 #if _SQUID_WINDOWS_
135 const int result = socket_read_method(fd_, buf, size);
136 #else
137 const int result = default_read_method(fd_, buf, size);
138 #endif
139 const int xerrno = errno;
140 debugs(83, 5, "FD " << fd_ << " read " << result << " <= " << size);
141
142 BIO_clear_retry_flags(table);
143 if (result < 0) {
144 const bool ignoreError = ignoreErrno(xerrno) != 0;
145 debugs(83, 5, "error: " << xerrno << " ignored: " << ignoreError);
146 if (ignoreError)
147 BIO_set_retry_read(table);
148 }
149
150 return result;
151 }
152
153 /// Called whenever the SSL connection state changes, an alert appears, or an
154 /// error occurs. See SSL_set_info_callback().
155 void
156 Ssl::Bio::stateChanged(const SSL *ssl, int where, int ret)
157 {
158 // Here we can use (where & STATE) to check the current state.
159 // Many STATE values are possible, including: SSL_CB_CONNECT_LOOP,
160 // SSL_CB_ACCEPT_LOOP, SSL_CB_HANDSHAKE_START, and SSL_CB_HANDSHAKE_DONE.
161 // For example:
162 // if (where & SSL_CB_HANDSHAKE_START)
163 // debugs(83, 9, "Trying to establish the SSL connection");
164 // else if (where & SSL_CB_HANDSHAKE_DONE)
165 // debugs(83, 9, "SSL connection established");
166
167 debugs(83, 7, "FD " << fd_ << " now: 0x" << std::hex << where << std::dec << ' ' <<
168 SSL_state_string(ssl) << " (" << SSL_state_string_long(ssl) << ")");
169 }
170
171 Ssl::ClientBio::ClientBio(const int anFd):
172 Bio(anFd),
173 holdRead_(false),
174 holdWrite_(false),
175 helloSize(0),
176 abortReason(nullptr)
177 {
178 renegotiations.configure(10*1000);
179 }
180
181 void
182 Ssl::ClientBio::stateChanged(const SSL *ssl, int where, int ret)
183 {
184 Ssl::Bio::stateChanged(ssl, where, ret);
185 // detect client-initiated renegotiations DoS (CVE-2011-1473)
186 if (where & SSL_CB_HANDSHAKE_START) {
187 const int reneg = renegotiations.count(1);
188
189 if (abortReason)
190 return; // already decided and informed the admin
191
192 if (reneg > RenegotiationsLimit) {
193 abortReason = "renegotiate requests flood";
194 debugs(83, DBG_IMPORTANT, "Terminating TLS connection [from " << fd_table[fd_].ipaddr << "] due to " << abortReason << ". This connection received " <<
195 reneg << " renegotiate requests in the last " <<
196 RenegotiationsWindow << " seconds (and " <<
197 renegotiations.remembered() << " requests total).");
198 }
199 }
200 }
201
202 int
203 Ssl::ClientBio::write(const char *buf, int size, BIO *table)
204 {
205 if (abortReason) {
206 debugs(83, 3, "BIO on FD " << fd_ << " is aborted");
207 BIO_clear_retry_flags(table);
208 return -1;
209 }
210
211 if (holdWrite_) {
212 BIO_set_retry_write(table);
213 return 0;
214 }
215
216 return Ssl::Bio::write(buf, size, table);
217 }
218
219 int
220 Ssl::ClientBio::read(char *buf, int size, BIO *table)
221 {
222 if (abortReason) {
223 debugs(83, 3, "BIO on FD " << fd_ << " is aborted");
224 BIO_clear_retry_flags(table);
225 return -1;
226 }
227
228 if (holdRead_) {
229 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
230 BIO_set_retry_read(table);
231 return -1;
232 }
233
234 if (!rbuf.isEmpty()) {
235 int bytes = (size <= (int)rbuf.length() ? size : rbuf.length());
236 memcpy(buf, rbuf.rawContent(), bytes);
237 rbuf.consume(bytes);
238 return bytes;
239 } else
240 return Ssl::Bio::read(buf, size, table);
241
242 return -1;
243 }
244
245 Ssl::ServerBio::ServerBio(const int anFd):
246 Bio(anFd),
247 helloMsgSize(0),
248 helloBuild(false),
249 allowSplice(false),
250 allowBump(false),
251 holdWrite_(false),
252 holdRead_(true),
253 record_(false),
254 parsedHandshake(false),
255 parseError(false),
256 bumpMode_(bumpNone),
257 rbufConsumePos(0)
258 {
259 }
260
261 void
262 Ssl::ServerBio::stateChanged(const SSL *ssl, int where, int ret)
263 {
264 Ssl::Bio::stateChanged(ssl, where, ret);
265 }
266
267 void
268 Ssl::ServerBio::setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &aHello)
269 {
270 clientTlsDetails = details;
271 clientSentHello = aHello;
272 };
273
274 int
275 Ssl::ServerBio::read(char *buf, int size, BIO *table)
276 {
277 if (parsedHandshake) // done parsing TLS Hello
278 return readAndGive(buf, size, table);
279 else
280 return readAndParse(buf, size, table);
281 }
282
283 /// Read and give everything to OpenSSL.
284 int
285 Ssl::ServerBio::readAndGive(char *buf, const int size, BIO *table)
286 {
287 // If we have unused buffered bytes, give those bytes to OpenSSL now,
288 // before reading more. TODO: Read if we have buffered less than size?
289 if (rbufConsumePos < rbuf.length())
290 return giveBuffered(buf, size);
291
292 if (record_) {
293 const int result = readAndBuffer(table);
294 if (result <= 0)
295 return result;
296 return giveBuffered(buf, size);
297 }
298
299 return Ssl::Bio::read(buf, size, table);
300 }
301
302 /// Read and give everything to our parser.
303 /// When/if parsing is finished (successfully or not), start giving to OpenSSL.
304 int
305 Ssl::ServerBio::readAndParse(char *buf, const int size, BIO *table)
306 {
307 const int result = readAndBuffer(table);
308 if (result <= 0)
309 return result;
310
311 try {
312 if (!parser_.parseHello(rbuf)) {
313 // need more data to finish parsing
314 BIO_set_retry_read(table);
315 return -1;
316 }
317 parsedHandshake = true; // done parsing (successfully)
318 }
319 catch (const std::exception &ex) {
320 debugs(83, 2, "parsing error on FD " << fd_ << ": " << ex.what());
321 parsedHandshake = true; // done parsing (due to an error)
322 parseError = true;
323 }
324
325 if (holdRead_) {
326 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
327 BIO_set_retry_read(table);
328 return -1;
329 }
330
331 return giveBuffered(buf, size);
332 }
333
334 /// Reads more data into the read buffer. Returns either the number of bytes
335 /// read or, on errors (including "try again" errors), a negative number.
336 int
337 Ssl::ServerBio::readAndBuffer(BIO *table)
338 {
339 char *space = rbuf.rawSpace(SQUID_TCP_SO_RCVBUF);
340 const int result = Ssl::Bio::read(space, rbuf.spaceSize(), table);
341 if (result <= 0)
342 return result;
343
344 rbuf.forceSize(rbuf.length() + result);
345 return result;
346 }
347
348 /// give previously buffered bytes to OpenSSL
349 /// returns the number of bytes given
350 int
351 Ssl::ServerBio::giveBuffered(char *buf, const int size)
352 {
353 if (rbuf.length() <= rbufConsumePos)
354 return -1; // buffered nothing yet
355
356 const int unsent = rbuf.length() - rbufConsumePos;
357 const int bytes = (size <= unsent ? size : unsent);
358 memcpy(buf, rbuf.rawContent() + rbufConsumePos, bytes);
359 rbufConsumePos += bytes;
360 debugs(83, 7, bytes << "<=" << size << " bytes to OpenSSL");
361 return bytes;
362 }
363
364 // This function makes the required checks to examine if the client hello
365 // message is compatible with the features provided by OpenSSL toolkit.
366 // If the features are compatible and can be supported it tries to rewrite SSL
367 // structure members, to replace the hello message created by openSSL, with the
368 // web client SSL hello message.
369 // This is mostly possible in the cases where the web client uses openSSL
370 // library similar with this one used by squid.
371 static bool
372 adjustSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, SBuf &helloMessage)
373 {
374 #if SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK
375 if (!details)
376 return false;
377
378 if (!ssl->s3) {
379 debugs(83, 5, "No SSLv3 data found!");
380 return false;
381 }
382
383 // If the client supports compression but our context does not support
384 // we can not adjust.
385 #if !defined(OPENSSL_NO_COMP)
386 const bool requireCompression = (details->compressionSupported && ssl->ctx->comp_methods == nullptr);
387 #else
388 const bool requireCompression = details->compressionSupported;
389 #endif
390 if (requireCompression) {
391 debugs(83, 5, "Client Hello Data supports compression, but we do not!");
392 return false;
393 }
394
395 #if !defined(SSL_TLSEXT_HB_ENABLED)
396 if (details->doHeartBeats) {
397 debugs(83, 5, "Client Hello Data supports HeartBeats but we do not support!");
398 return false;
399 }
400 #endif
401
402 if (details->unsupportedExtensions) {
403 debugs(83, 5, "Client Hello contains extensions that we do not support!");
404 return false;
405 }
406
407 SSL3_BUFFER *wb=&(ssl->s3->wbuf);
408 if (wb->len < (size_t)helloMessage.length()) {
409 debugs(83, 5, "Client Hello exceeds OpenSSL buffer: " << helloMessage.length() << " >= " << wb->len);
410 return false;
411 }
412
413 /* Check whether all on-the-wire ciphers are supported by OpenSSL. */
414
415 const auto &wireCiphers = details->ciphers;
416 Security::TlsDetails::Ciphers::size_type ciphersToFind = wireCiphers.size();
417
418 // RFC 5746: "TLS_EMPTY_RENEGOTIATION_INFO_SCSV is not a true cipher suite".
419 // It is commonly seen on the wire, including in from-OpenSSL traffic, but
420 // SSL_get_ciphers() does not return this _pseudo_ cipher suite in my tests.
421 // If OpenSSL supports scsvCipher, we count it (at most once) further below.
422 #if defined(TLSEXT_TYPE_renegotiate)
423 // the 0x00FFFF mask converts 3-byte OpenSSL cipher to our 2-byte cipher
424 const uint16_t scsvCipher = SSL3_CK_SCSV & 0x00FFFF;
425 #else
426 const uint16_t scsvCipher = 0;
427 #endif
428
429 STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(ssl);
430 const int supportedCipherCount = sk_SSL_CIPHER_num(cipher_stack);
431 for (int idx = 0; idx < supportedCipherCount && ciphersToFind > 0; ++idx) {
432 const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(cipher_stack, idx);
433 const auto id = SSL_CIPHER_get_id(cipher) & 0x00FFFF;
434 if (wireCiphers.find(id) != wireCiphers.end() && (!scsvCipher || id != scsvCipher))
435 --ciphersToFind;
436 }
437
438 if (ciphersToFind > 0 && scsvCipher && wireCiphers.find(scsvCipher) != wireCiphers.end())
439 --ciphersToFind;
440
441 if (ciphersToFind > 0) {
442 // TODO: Add slowlyReportUnsupportedCiphers() to slowly find and report each of them
443 debugs(83, 5, "Client Hello Data has " << ciphersToFind << " ciphers that we do not support!");
444 return false;
445 }
446
447 debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
448
449 //Adjust ssl structure data.
450 // We need to fix the random in SSL struct:
451 if (details->clientRandom.length() == SSL3_RANDOM_SIZE)
452 memcpy(ssl->s3->client_random, details->clientRandom.c_str(), SSL3_RANDOM_SIZE);
453 memcpy(wb->buf, helloMessage.rawContent(), helloMessage.length());
454 wb->left = helloMessage.length();
455
456 size_t mainHelloSize = helloMessage.length() - 5;
457 const char *mainHello = helloMessage.rawContent() + 5;
458 assert((size_t)ssl->init_buf->max > mainHelloSize);
459 memcpy(ssl->init_buf->data, mainHello, mainHelloSize);
460 debugs(83, 5, "Hello Data init and adjustd sizes :" << ssl->init_num << " = "<< mainHelloSize);
461 ssl->init_num = mainHelloSize;
462 ssl->s3->wpend_ret = mainHelloSize;
463 ssl->s3->wpend_tot = mainHelloSize;
464 return true;
465 #else
466 return false;
467 #endif
468 }
469
470 int
471 Ssl::ServerBio::write(const char *buf, int size, BIO *table)
472 {
473
474 if (holdWrite_) {
475 debugs(83, 7, "postpone writing " << size << " bytes to SSL FD " << fd_);
476 BIO_set_retry_write(table);
477 return -1;
478 }
479
480 if (!helloBuild && (bumpMode_ == Ssl::bumpPeek || bumpMode_ == Ssl::bumpStare)) {
481 // buf contains OpenSSL-generated ClientHello. We assume it has a
482 // complete ClientHello and nothing else, but cannot fully verify
483 // that quickly. We only verify that buf starts with a v3+ record
484 // containing ClientHello.
485 Must(size >= 2); // enough for version and content_type checks below
486 Must(buf[1] >= 3); // record's version.major; determines buf[0] meaning
487 Must(buf[0] == 22); // TLSPlaintext.content_type == handshake in v3+
488
489 //Hello message is the first message we write to server
490 assert(helloMsg.isEmpty());
491
492 if (auto ssl = fd_table[fd_].ssl.get()) {
493 if (bumpMode_ == Ssl::bumpPeek) {
494 // we should not be here if we failed to parse the client-sent ClientHello
495 Must(!clientSentHello.isEmpty());
496 if (adjustSSL(ssl, clientTlsDetails, clientSentHello))
497 allowBump = true;
498 allowSplice = true;
499 // Replace OpenSSL-generated ClientHello with client-sent one.
500 helloMsg.append(clientSentHello);
501 debugs(83, 7, "FD " << fd_ << ": Using client-sent ClientHello for peek mode");
502 } else { /*Ssl::bumpStare*/
503 allowBump = true;
504 if (!clientSentHello.isEmpty() && adjustSSL(ssl, clientTlsDetails, clientSentHello)) {
505 allowSplice = true;
506 helloMsg.append(clientSentHello);
507 debugs(83, 7, "FD " << fd_ << ": Using client-sent ClientHello for stare mode");
508 }
509 }
510 }
511 // if we did not use the client-sent ClientHello, then use the OpenSSL-generated one
512 if (helloMsg.isEmpty())
513 helloMsg.append(buf, size);
514
515 helloBuild = true;
516 helloMsgSize = helloMsg.length();
517 //allowBump = true;
518
519 if (allowSplice) {
520 // Do not write yet.....
521 BIO_set_retry_write(table);
522 return -1;
523 }
524 }
525
526 if (!helloMsg.isEmpty()) {
527 debugs(83, 7, "buffered write for FD " << fd_);
528 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
529 helloMsg.consume(ret);
530 if (!helloMsg.isEmpty()) {
531 // We need to retry sendind data.
532 // Say to openSSL to retry sending hello message
533 BIO_set_retry_write(table);
534 return -1;
535 }
536
537 // Sending hello message complete. Do not send more data for now...
538 holdWrite_ = true;
539
540 // spoof openSSL that we write what it ask us to write
541 return size;
542 } else
543 return Ssl::Bio::write(buf, size, table);
544 }
545
546 void
547 Ssl::ServerBio::flush(BIO *table)
548 {
549 if (!helloMsg.isEmpty()) {
550 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
551 helloMsg.consume(ret);
552 }
553 }
554
555 bool
556 Ssl::ServerBio::resumingSession()
557 {
558 return parser_.resumingSession;
559 }
560
561 /// initializes BIO table after allocation
562 static int
563 squid_bio_create(BIO *bi)
564 {
565 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
566 bi->init = 0; // set when we store Bio object and socket fd (BIO_C_SET_FD)
567 bi->num = 0;
568 bi->flags = 0;
569 #else
570 // No need to set more, openSSL initialize BIO memory to zero.
571 #endif
572
573 BIO_set_data(bi, NULL);
574 return 1;
575 }
576
577 /// cleans BIO table before deallocation
578 static int
579 squid_bio_destroy(BIO *table)
580 {
581 delete static_cast<Ssl::Bio*>(BIO_get_data(table));
582 BIO_set_data(table, NULL);
583 return 1;
584 }
585
586 /// wrapper for Bio::write()
587 static int
588 squid_bio_write(BIO *table, const char *buf, int size)
589 {
590 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
591 assert(bio);
592 return bio->write(buf, size, table);
593 }
594
595 /// wrapper for Bio::read()
596 static int
597 squid_bio_read(BIO *table, char *buf, int size)
598 {
599 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
600 assert(bio);
601 return bio->read(buf, size, table);
602 }
603
604 /// implements puts() via write()
605 static int
606 squid_bio_puts(BIO *table, const char *str)
607 {
608 assert(str);
609 return squid_bio_write(table, str, strlen(str));
610 }
611
612 /// other BIO manipulations (those without dedicated callbacks in BIO table)
613 static long
614 squid_bio_ctrl(BIO *table, int cmd, long arg1, void *arg2)
615 {
616 debugs(83, 5, table << ' ' << cmd << '(' << arg1 << ", " << arg2 << ')');
617
618 switch (cmd) {
619 case BIO_C_SET_FD: {
620 assert(arg2);
621 const int fd = *static_cast<int*>(arg2);
622 Ssl::Bio *bio;
623 if (arg1 == Ssl::Bio::BIO_TO_SERVER)
624 bio = new Ssl::ServerBio(fd);
625 else
626 bio = new Ssl::ClientBio(fd);
627 assert(!BIO_get_data(table));
628 BIO_set_data(table, bio);
629 BIO_set_init(table, 1);
630 return 0;
631 }
632
633 case BIO_C_GET_FD:
634 if (BIO_get_init(table)) {
635 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
636 assert(bio);
637 if (arg2)
638 *static_cast<int*>(arg2) = bio->fd();
639 return bio->fd();
640 }
641 return -1;
642
643 case BIO_CTRL_DUP:
644 // Should implemented if the SSL_dup openSSL API function
645 // used anywhere in squid.
646 return 0;
647
648 case BIO_CTRL_FLUSH:
649 if (BIO_get_init(table)) {
650 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
651 assert(bio);
652 bio->flush(table);
653 return 1;
654 }
655 return 0;
656
657 /* we may also need to implement these:
658 case BIO_CTRL_RESET:
659 case BIO_C_FILE_SEEK:
660 case BIO_C_FILE_TELL:
661 case BIO_CTRL_INFO:
662 case BIO_CTRL_GET_CLOSE:
663 case BIO_CTRL_SET_CLOSE:
664 case BIO_CTRL_PENDING:
665 case BIO_CTRL_WPENDING:
666 */
667 default:
668 return 0;
669
670 }
671
672 return 0; /* NOTREACHED */
673 }
674
675 /// wrapper for Bio::stateChanged()
676 static void
677 squid_ssl_info(const SSL *ssl, int where, int ret)
678 {
679 if (BIO *table = SSL_get_rbio(ssl)) {
680 if (Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table)))
681 bio->stateChanged(ssl, where, ret);
682 }
683 }
684
685 void
686 applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode)
687 {
688 // To increase the possibility for bumping after peek mode selection or
689 // splicing after stare mode selection it is good to set the
690 // SSL protocol version.
691 // The SSL_set_ssl_method is wrong here because it will restrict the
692 // permitted transport version to be identical to the version used in the
693 // ClientHello message.
694 // For example will prevent comunnicating with a tls1.0 server if the
695 // client sent and tlsv1.2 Hello message.
696 #if defined(TLSEXT_NAMETYPE_host_name)
697 if (!details->serverName.isEmpty()) {
698 SSL_set_tlsext_host_name(ssl, details->serverName.c_str());
699 }
700 #endif
701
702 if (!details->ciphers.empty()) {
703 SBuf strCiphers;
704 for (auto cipherId: details->ciphers) {
705 unsigned char cbytes[3];
706 cbytes[0] = (cipherId >> 8) & 0xFF;
707 cbytes[1] = cipherId & 0xFF;
708 cbytes[2] = 0;
709 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
710 const SSL_METHOD *method = SSLv23_method();
711 const SSL_CIPHER *c = method->get_cipher_by_char(cbytes);
712 #else
713 const SSL_CIPHER *c = SSL_CIPHER_find(ssl, cbytes);
714 #endif
715 if (c != NULL) {
716 if (!strCiphers.isEmpty())
717 strCiphers.append(":");
718 strCiphers.append(SSL_CIPHER_get_name(c));
719 }
720 }
721 if (!strCiphers.isEmpty())
722 SSL_set_cipher_list(ssl, strCiphers.c_str());
723 }
724
725 #if defined(SSL_OP_NO_COMPRESSION) /* XXX: OpenSSL 0.9.8k lacks SSL_OP_NO_COMPRESSION */
726 if (!details->compressionSupported)
727 SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
728 #endif
729
730 #if defined(TLSEXT_STATUSTYPE_ocsp)
731 if (details->tlsStatusRequest)
732 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
733 #endif
734
735 #if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
736 if (!details->tlsAppLayerProtoNeg.isEmpty()) {
737 if (bumpMode == Ssl::bumpPeek)
738 SSL_set_alpn_protos(ssl, (const unsigned char*)details->tlsAppLayerProtoNeg.rawContent(), details->tlsAppLayerProtoNeg.length());
739 else {
740 static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
741 SSL_set_alpn_protos(ssl, supported_protos, sizeof(supported_protos));
742 }
743 }
744 #endif
745 }
746
747 #endif // USE_OPENSSL
748