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