]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/bio.cc
2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 83 SSL accelerator support */
12 #include "ssl/support.h"
14 /* support.cc says this is needed */
21 #include "ip/Address.h"
22 #include "parser/BinaryTokenizer.h"
23 #include "SquidTime.h"
26 #if HAVE_OPENSSL_SSL_H
27 #include <openssl/ssl.h>
31 extern int socket_read_method(int, char *, int);
32 extern int socket_write_method(int, const char *, int);
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
);
44 static void squid_ssl_info(const SSL
*ssl
, int where
, int ret
);
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
= {
55 NULL
, // squid_bio_gets not supported
59 NULL
// squid_callback_ctrl not supported
62 static BIO_METHOD
*SquidMethods
= NULL
;
66 Ssl::Bio::Create(const int fd
, Ssl::Bio::Type type
)
68 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
69 BIO_METHOD
*useMethod
= &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
);
81 const BIO_METHOD
*useMethod
= SquidMethods
;
84 if (BIO
*bio
= BIO_new(useMethod
)) {
85 BIO_int_ctrl(bio
, BIO_C_SET_FD
, type
, fd
);
92 Ssl::Bio::Link(SSL
*ssl
, BIO
*bio
)
94 SSL_set_bio(ssl
, bio
, bio
); // cannot fail
95 SSL_set_info_callback(ssl
, &squid_ssl_info
); // does not provide diagnostic
98 Ssl::Bio::Bio(const int anFd
): fd_(anFd
)
100 debugs(83, 7, "Bio constructed, this=" << this << " FD " << fd_
);
105 debugs(83, 7, "Bio destructing, this=" << this << " FD " << fd_
);
108 int Ssl::Bio::write(const char *buf
, int size
, BIO
*table
)
112 const int result
= socket_write_method(fd_
, buf
, size
);
114 const int result
= default_write_method(fd_
, buf
, size
);
116 const int xerrno
= errno
;
117 debugs(83, 5, "FD " << fd_
<< " wrote " << result
<< " <= " << size
);
119 BIO_clear_retry_flags(table
);
121 const bool ignoreError
= ignoreErrno(xerrno
) != 0;
122 debugs(83, 5, "error: " << xerrno
<< " ignored: " << ignoreError
);
124 BIO_set_retry_write(table
);
131 Ssl::Bio::read(char *buf
, int size
, BIO
*table
)
135 const int result
= socket_read_method(fd_
, buf
, size
);
137 const int result
= default_read_method(fd_
, buf
, size
);
139 const int xerrno
= errno
;
140 debugs(83, 5, "FD " << fd_
<< " read " << result
<< " <= " << size
);
142 BIO_clear_retry_flags(table
);
144 const bool ignoreError
= ignoreErrno(xerrno
) != 0;
145 debugs(83, 5, "error: " << xerrno
<< " ignored: " << ignoreError
);
147 BIO_set_retry_read(table
);
153 /// Called whenever the SSL connection state changes, an alert appears, or an
154 /// error occurs. See SSL_set_info_callback().
156 Ssl::Bio::stateChanged(const SSL
*ssl
, int where
, int ret
)
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.
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");
167 debugs(83, 7, "FD " << fd_
<< " now: 0x" << std::hex
<< where
<< std::dec
<< ' ' <<
168 SSL_state_string(ssl
) << " (" << SSL_state_string_long(ssl
) << ")");
171 Ssl::ClientBio::ClientBio(const int anFd
):
178 renegotiations
.configure(10*1000);
182 Ssl::ClientBio::stateChanged(const SSL
*ssl
, int where
, int ret
)
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);
190 return; // already decided and informed the admin
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).");
203 Ssl::ClientBio::write(const char *buf
, int size
, BIO
*table
)
206 debugs(83, 3, "BIO on FD " << fd_
<< " is aborted");
207 BIO_clear_retry_flags(table
);
212 BIO_set_retry_write(table
);
216 return Ssl::Bio::write(buf
, size
, table
);
220 Ssl::ClientBio::read(char *buf
, int size
, BIO
*table
)
223 debugs(83, 3, "BIO on FD " << fd_
<< " is aborted");
224 BIO_clear_retry_flags(table
);
229 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size
<< "bytes)");
230 BIO_set_retry_read(table
);
234 if (!rbuf
.isEmpty()) {
235 int bytes
= (size
<= (int)rbuf
.length() ? size
: rbuf
.length());
236 memcpy(buf
, rbuf
.rawContent(), bytes
);
240 return Ssl::Bio::read(buf
, size
, table
);
245 Ssl::ServerBio::ServerBio(const int anFd
):
254 parsedHandshake(false),
262 Ssl::ServerBio::stateChanged(const SSL
*ssl
, int where
, int ret
)
264 Ssl::Bio::stateChanged(ssl
, where
, ret
);
268 Ssl::ServerBio::setClientFeatures(Security::TlsDetails::Pointer
const &details
, SBuf
const &aHello
)
270 clientTlsDetails
= details
;
271 clientSentHello
= aHello
;
275 Ssl::ServerBio::read(char *buf
, int size
, BIO
*table
)
277 if (parsedHandshake
) // done parsing TLS Hello
278 return readAndGive(buf
, size
, table
);
280 return readAndParse(buf
, size
, table
);
283 /// Read and give everything to OpenSSL.
285 Ssl::ServerBio::readAndGive(char *buf
, const int size
, BIO
*table
)
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
);
293 const int result
= readAndBuffer(table
);
296 return giveBuffered(buf
, size
);
299 return Ssl::Bio::read(buf
, size
, table
);
302 /// Read and give everything to our parser.
303 /// When/if parsing is finished (successfully or not), start giving to OpenSSL.
305 Ssl::ServerBio::readAndParse(char *buf
, const int size
, BIO
*table
)
307 const int result
= readAndBuffer(table
);
312 if (!parser_
.parseHello(rbuf
)) {
313 // need more data to finish parsing
314 BIO_set_retry_read(table
);
317 parsedHandshake
= true; // done parsing (successfully)
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)
326 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size
<< "bytes)");
327 BIO_set_retry_read(table
);
331 return giveBuffered(buf
, size
);
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.
337 Ssl::ServerBio::readAndBuffer(BIO
*table
)
339 char *space
= rbuf
.rawSpace(SQUID_TCP_SO_RCVBUF
);
340 const int result
= Ssl::Bio::read(space
, rbuf
.spaceSize(), table
);
344 rbuf
.forceSize(rbuf
.length() + result
);
348 /// give previously buffered bytes to OpenSSL
349 /// returns the number of bytes given
351 Ssl::ServerBio::giveBuffered(char *buf
, const int size
)
353 if (rbuf
.length() <= rbufConsumePos
)
354 return -1; // buffered nothing yet
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");
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.
372 adjustSSL(SSL
*ssl
, Security::TlsDetails::Pointer
const &details
, SBuf
&helloMessage
)
374 #if SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK
379 debugs(83, 5, "No SSLv3 data found!");
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);
388 const bool requireCompression
= details
->compressionSupported
;
390 if (requireCompression
) {
391 debugs(83, 5, "Client Hello Data supports compression, but we do not!");
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!");
402 if (details
->unsupportedExtensions
) {
403 debugs(83, 5, "Client Hello contains extensions that we do not support!");
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
);
413 /* Check whether all on-the-wire ciphers are supported by OpenSSL. */
415 const auto &wireCiphers
= details
->ciphers
;
416 Security::TlsDetails::Ciphers::size_type ciphersToFind
= wireCiphers
.size();
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;
426 const uint16_t scsvCipher
= 0;
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
))
438 if (ciphersToFind
> 0 && scsvCipher
&& wireCiphers
.find(scsvCipher
) != wireCiphers
.end())
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!");
447 debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
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();
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
;
471 Ssl::ServerBio::write(const char *buf
, int size
, BIO
*table
)
475 debugs(83, 7, "postpone writing " << size
<< " bytes to SSL FD " << fd_
);
476 BIO_set_retry_write(table
);
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+
489 //Hello message is the first message we write to server
490 assert(helloMsg
.isEmpty());
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
))
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*/
504 if (!clientSentHello
.isEmpty() && adjustSSL(ssl
, clientTlsDetails
, clientSentHello
)) {
506 helloMsg
.append(clientSentHello
);
507 debugs(83, 7, "FD " << fd_
<< ": Using client-sent ClientHello for stare mode");
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
);
516 helloMsgSize
= helloMsg
.length();
520 // Do not write yet.....
521 BIO_set_retry_write(table
);
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
);
537 // Sending hello message complete. Do not send more data for now...
540 // spoof openSSL that we write what it ask us to write
543 return Ssl::Bio::write(buf
, size
, table
);
547 Ssl::ServerBio::flush(BIO
*table
)
549 if (!helloMsg
.isEmpty()) {
550 int ret
= Ssl::Bio::write(helloMsg
.rawContent(), helloMsg
.length(), table
);
551 helloMsg
.consume(ret
);
556 Ssl::ServerBio::resumingSession()
558 return parser_
.resumingSession
;
561 /// initializes BIO table after allocation
563 squid_bio_create(BIO
*bi
)
565 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
566 bi
->init
= 0; // set when we store Bio object and socket fd (BIO_C_SET_FD)
570 // No need to set more, openSSL initialize BIO memory to zero.
573 BIO_set_data(bi
, NULL
);
577 /// cleans BIO table before deallocation
579 squid_bio_destroy(BIO
*table
)
581 delete static_cast<Ssl::Bio
*>(BIO_get_data(table
));
582 BIO_set_data(table
, NULL
);
586 /// wrapper for Bio::write()
588 squid_bio_write(BIO
*table
, const char *buf
, int size
)
590 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(BIO_get_data(table
));
592 return bio
->write(buf
, size
, table
);
595 /// wrapper for Bio::read()
597 squid_bio_read(BIO
*table
, char *buf
, int size
)
599 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(BIO_get_data(table
));
601 return bio
->read(buf
, size
, table
);
604 /// implements puts() via write()
606 squid_bio_puts(BIO
*table
, const char *str
)
609 return squid_bio_write(table
, str
, strlen(str
));
612 /// other BIO manipulations (those without dedicated callbacks in BIO table)
614 squid_bio_ctrl(BIO
*table
, int cmd
, long arg1
, void *arg2
)
616 debugs(83, 5, table
<< ' ' << cmd
<< '(' << arg1
<< ", " << arg2
<< ')');
621 const int fd
= *static_cast<int*>(arg2
);
623 if (arg1
== Ssl::Bio::BIO_TO_SERVER
)
624 bio
= new Ssl::ServerBio(fd
);
626 bio
= new Ssl::ClientBio(fd
);
627 assert(!BIO_get_data(table
));
628 BIO_set_data(table
, bio
);
629 BIO_set_init(table
, 1);
634 if (BIO_get_init(table
)) {
635 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(BIO_get_data(table
));
638 *static_cast<int*>(arg2
) = bio
->fd();
644 // Should implemented if the SSL_dup openSSL API function
645 // used anywhere in squid.
649 if (BIO_get_init(table
)) {
650 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(BIO_get_data(table
));
657 /* we may also need to implement these:
659 case BIO_C_FILE_SEEK:
660 case BIO_C_FILE_TELL:
662 case BIO_CTRL_GET_CLOSE:
663 case BIO_CTRL_SET_CLOSE:
664 case BIO_CTRL_PENDING:
665 case BIO_CTRL_WPENDING:
672 return 0; /* NOTREACHED */
675 /// wrapper for Bio::stateChanged()
677 squid_ssl_info(const SSL
*ssl
, int where
, int ret
)
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
);
686 applyTlsDetailsToSSL(SSL
*ssl
, Security::TlsDetails::Pointer
const &details
, Ssl::BumpMode bumpMode
)
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());
702 if (!details
->ciphers
.empty()) {
704 for (auto cipherId
: details
->ciphers
) {
705 unsigned char cbytes
[3];
706 cbytes
[0] = (cipherId
>> 8) & 0xFF;
707 cbytes
[1] = cipherId
& 0xFF;
709 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
710 const SSL_METHOD
*method
= SSLv23_method();
711 const SSL_CIPHER
*c
= method
->get_cipher_by_char(cbytes
);
713 const SSL_CIPHER
*c
= SSL_CIPHER_find(ssl
, cbytes
);
716 if (!strCiphers
.isEmpty())
717 strCiphers
.append(":");
718 strCiphers
.append(SSL_CIPHER_get_name(c
));
721 if (!strCiphers
.isEmpty())
722 SSL_set_cipher_list(ssl
, strCiphers
.c_str());
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
);
730 #if defined(TLSEXT_STATUSTYPE_ocsp)
731 if (details
->tlsStatusRequest
)
732 SSL_set_tlsext_status_type(ssl
, TLSEXT_STATUSTYPE_ocsp
);
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());
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
));
747 #endif // USE_OPENSSL