]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/bio.cc
2 * Copyright (C) 1996-2016 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"
25 #if HAVE_OPENSSL_SSL_H
26 #include <openssl/ssl.h>
30 extern int socket_read_method(int, char *, int);
31 extern int socket_write_method(int, const char *, int);
35 static int squid_bio_write(BIO
*h
, const char *buf
, int num
);
36 static int squid_bio_read(BIO
*h
, char *buf
, int size
);
37 static int squid_bio_puts(BIO
*h
, const char *str
);
38 //static int squid_bio_gets(BIO *h, char *str, int size);
39 static long squid_bio_ctrl(BIO
*h
, int cmd
, long arg1
, void *arg2
);
40 static int squid_bio_create(BIO
*h
);
41 static int squid_bio_destroy(BIO
*data
);
43 static void squid_ssl_info(const SSL
*ssl
, int where
, int ret
);
45 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
46 /// Initialization structure for the BIO table with
47 /// Squid-specific methods and BIO method wrappers.
48 static BIO_METHOD SquidMethods
= {
54 NULL
, // squid_bio_gets not supported
58 NULL
// squid_callback_ctrl not supported
61 static BIO_METHOD
*SquidMethods
= NULL
;
65 Ssl::Bio::Create(const int fd
, Ssl::Bio::Type type
)
67 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
68 BIO_METHOD
*useMethod
= &SquidMethods
;
71 SquidMethods
= BIO_meth_new(BIO_TYPE_SOCKET
, "squid");
72 BIO_meth_set_write(SquidMethods
, squid_bio_write
);
73 BIO_meth_set_read(SquidMethods
, squid_bio_read
);
74 BIO_meth_set_puts(SquidMethods
, squid_bio_puts
);
75 BIO_meth_set_gets(SquidMethods
, NULL
);
76 BIO_meth_set_ctrl(SquidMethods
, squid_bio_ctrl
);
77 BIO_meth_set_create(SquidMethods
, squid_bio_create
);
78 BIO_meth_set_destroy(SquidMethods
, squid_bio_destroy
);
80 const BIO_METHOD
*useMethod
= SquidMethods
;
83 if (BIO
*bio
= BIO_new(useMethod
)) {
84 BIO_int_ctrl(bio
, BIO_C_SET_FD
, type
, fd
);
91 Ssl::Bio::Link(SSL
*ssl
, BIO
*bio
)
93 SSL_set_bio(ssl
, bio
, bio
); // cannot fail
94 SSL_set_info_callback(ssl
, &squid_ssl_info
); // does not provide diagnostic
97 Ssl::Bio::Bio(const int anFd
): fd_(anFd
)
99 debugs(83, 7, "Bio constructed, this=" << this << " FD " << fd_
);
104 debugs(83, 7, "Bio destructing, this=" << this << " FD " << fd_
);
107 int Ssl::Bio::write(const char *buf
, int size
, BIO
*table
)
111 const int result
= socket_write_method(fd_
, buf
, size
);
113 const int result
= default_write_method(fd_
, buf
, size
);
115 const int xerrno
= errno
;
116 debugs(83, 5, "FD " << fd_
<< " wrote " << result
<< " <= " << size
);
118 BIO_clear_retry_flags(table
);
120 const bool ignoreError
= ignoreErrno(xerrno
) != 0;
121 debugs(83, 5, "error: " << xerrno
<< " ignored: " << ignoreError
);
123 BIO_set_retry_write(table
);
130 Ssl::Bio::read(char *buf
, int size
, BIO
*table
)
134 const int result
= socket_read_method(fd_
, buf
, size
);
136 const int result
= default_read_method(fd_
, buf
, size
);
138 const int xerrno
= errno
;
139 debugs(83, 5, "FD " << fd_
<< " read " << result
<< " <= " << size
);
141 BIO_clear_retry_flags(table
);
143 const bool ignoreError
= ignoreErrno(xerrno
) != 0;
144 debugs(83, 5, "error: " << xerrno
<< " ignored: " << ignoreError
);
146 BIO_set_retry_read(table
);
152 /// Called whenever the SSL connection state changes, an alert appears, or an
153 /// error occurs. See SSL_set_info_callback().
155 Ssl::Bio::stateChanged(const SSL
*ssl
, int where
, int ret
)
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.
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");
166 debugs(83, 7, "FD " << fd_
<< " now: 0x" << std::hex
<< where
<< std::dec
<< ' ' <<
167 SSL_state_string(ssl
) << " (" << SSL_state_string_long(ssl
) << ")");
171 Ssl::ClientBio::stateChanged(const SSL
*ssl
, int where
, int ret
)
173 Ssl::Bio::stateChanged(ssl
, where
, ret
);
177 Ssl::ClientBio::write(const char *buf
, int size
, BIO
*table
)
180 BIO_set_retry_write(table
);
184 return Ssl::Bio::write(buf
, size
, table
);
188 Ssl::ClientBio::read(char *buf
, int size
, BIO
*table
)
191 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size
<< "bytes)");
192 BIO_set_retry_read(table
);
196 if (!rbuf
.isEmpty()) {
197 int bytes
= (size
<= (int)rbuf
.length() ? size
: rbuf
.length());
198 memcpy(buf
, rbuf
.rawContent(), bytes
);
202 return Ssl::Bio::read(buf
, size
, table
);
207 Ssl::ServerBio::ServerBio(const int anFd
):
216 parsedHandshake(false),
224 Ssl::ServerBio::stateChanged(const SSL
*ssl
, int where
, int ret
)
226 Ssl::Bio::stateChanged(ssl
, where
, ret
);
230 Ssl::ServerBio::setClientFeatures(Security::TlsDetails::Pointer
const &details
, SBuf
const &aHello
)
232 clientTlsDetails
= details
;
233 clientHelloMessage
= aHello
;
237 Ssl::ServerBio::read(char *buf
, int size
, BIO
*table
)
239 if (parsedHandshake
) // done parsing TLS Hello
240 return readAndGive(buf
, size
, table
);
242 return readAndParse(buf
, size
, table
);
245 /// Read and give everything to OpenSSL.
247 Ssl::ServerBio::readAndGive(char *buf
, const int size
, BIO
*table
)
249 // If we have unused buffered bytes, give those bytes to OpenSSL now,
250 // before reading more. TODO: Read if we have buffered less than size?
251 if (rbufConsumePos
< rbuf
.length())
252 return giveBuffered(buf
, size
);
255 const int result
= readAndBuffer(table
);
258 return giveBuffered(buf
, size
);
261 return Ssl::Bio::read(buf
, size
, table
);
264 /// Read and give everything to our parser.
265 /// When/if parsing is finished (successfully or not), start giving to OpenSSL.
267 Ssl::ServerBio::readAndParse(char *buf
, const int size
, BIO
*table
)
269 const int result
= readAndBuffer(table
);
274 if (!parser_
.parseHello(rbuf
)) {
275 // need more data to finish parsing
276 BIO_set_retry_read(table
);
279 parsedHandshake
= true; // done parsing (successfully)
281 catch (const std::exception
&ex
) {
282 debugs(83, 2, "parsing error on FD " << fd_
<< ": " << ex
.what());
283 parsedHandshake
= true; // done parsing (due to an error)
288 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size
<< "bytes)");
289 BIO_set_retry_read(table
);
293 return giveBuffered(buf
, size
);
296 /// Reads more data into the read buffer. Returns either the number of bytes
297 /// read or, on errors (including "try again" errors), a negative number.
299 Ssl::ServerBio::readAndBuffer(BIO
*table
)
301 char *space
= rbuf
.rawSpace(SQUID_TCP_SO_RCVBUF
);
302 const int result
= Ssl::Bio::read(space
, rbuf
.spaceSize(), table
);
306 rbuf
.forceSize(rbuf
.length() + result
);
310 /// give previously buffered bytes to OpenSSL
311 /// returns the number of bytes given
313 Ssl::ServerBio::giveBuffered(char *buf
, const int size
)
315 if (rbuf
.length() <= rbufConsumePos
)
316 return -1; // buffered nothing yet
318 const int unsent
= rbuf
.length() - rbufConsumePos
;
319 const int bytes
= (size
<= unsent
? size
: unsent
);
320 memcpy(buf
, rbuf
.rawContent() + rbufConsumePos
, bytes
);
321 rbufConsumePos
+= bytes
;
322 debugs(83, 7, bytes
<< "<=" << size
<< " bytes to OpenSSL");
326 // This function makes the required checks to examine if the client hello
327 // message is compatible with the features provided by OpenSSL toolkit.
328 // If the features are compatible and can be supported it tries to rewrite SSL
329 // structure members, to replace the hello message created by openSSL, with the
330 // web client SSL hello message.
331 // This is mostly possible in the cases where the web client uses openSSL
332 // library similar with this one used by squid.
334 adjustSSL(SSL
*ssl
, Security::TlsDetails::Pointer
const &details
, SBuf
&helloMessage
)
336 #if SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK
338 debugs(83, 5, "No SSLv3 data found!");
342 // If the client supports compression but our context does not support
343 // we can not adjust.
344 #if !defined(OPENSSL_NO_COMP)
345 const bool requireCompression
= (details
->compressionSupported
&& ssl
->ctx
->comp_methods
== nullptr);
347 const bool requireCompression
= details
->compressionSupported
;
349 if (requireCompression
) {
350 debugs(83, 5, "Client Hello Data supports compression, but we do not!");
354 #if !defined(SSL_TLSEXT_HB_ENABLED)
355 if (details
->doHeartBeats
) {
356 debugs(83, 5, "Client Hello Data supports HeartBeats but we do not support!");
361 if (details
->unsupportedExtensions
) {
362 debugs(83, 5, "Client Hello contains extensions that we do not support!");
366 SSL3_BUFFER
*wb
=&(ssl
->s3
->wbuf
);
367 if (wb
->len
< (size_t)helloMessage
.length()) {
368 debugs(83, 5, "Client Hello exceeds OpenSSL buffer: " << helloMessage
.length() << " >= " << wb
->len
);
372 /* Check whether all on-the-wire ciphers are supported by OpenSSL. */
374 const auto &wireCiphers
= details
->ciphers
;
375 Security::TlsDetails::Ciphers::size_type ciphersToFind
= wireCiphers
.size();
377 // RFC 5746: "TLS_EMPTY_RENEGOTIATION_INFO_SCSV is not a true cipher suite".
378 // It is commonly seen on the wire, including in from-OpenSSL traffic, but
379 // SSL_get_ciphers() does not return this _pseudo_ cipher suite in my tests.
380 // If OpenSSL supports scsvCipher, we count it (at most once) further below.
381 #if defined(TLSEXT_TYPE_renegotiate)
382 // the 0x00FFFF mask converts 3-byte OpenSSL cipher to our 2-byte cipher
383 const uint16_t scsvCipher
= SSL3_CK_SCSV
& 0x00FFFF;
385 const uint16_t scsvCipher
= 0;
388 STACK_OF(SSL_CIPHER
) *cipher_stack
= SSL_get_ciphers(ssl
);
389 const int supportedCipherCount
= sk_SSL_CIPHER_num(cipher_stack
);
390 for (int idx
= 0; idx
< supportedCipherCount
&& ciphersToFind
> 0; ++idx
) {
391 const SSL_CIPHER
*cipher
= sk_SSL_CIPHER_value(cipher_stack
, idx
);
392 const auto id
= SSL_CIPHER_get_id(cipher
) & 0x00FFFF;
393 if (wireCiphers
.find(id
) != wireCiphers
.end() && (!scsvCipher
|| id
!= scsvCipher
))
397 if (ciphersToFind
> 0 && scsvCipher
&& wireCiphers
.find(scsvCipher
) != wireCiphers
.end())
400 if (ciphersToFind
> 0) {
401 // TODO: Add slowlyReportUnsupportedCiphers() to slowly find and report each of them
402 debugs(83, 5, "Client Hello Data has " << ciphersToFind
<< " ciphers that we do not support!");
406 debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
408 //Adjust ssl structure data.
409 // We need to fix the random in SSL struct:
410 if (details
->clientRandom
.length() == SSL3_RANDOM_SIZE
)
411 memcpy(ssl
->s3
->client_random
, details
->clientRandom
.c_str(), SSL3_RANDOM_SIZE
);
412 memcpy(wb
->buf
, helloMessage
.rawContent(), helloMessage
.length());
413 wb
->left
= helloMessage
.length();
415 size_t mainHelloSize
= helloMessage
.length() - 5;
416 const char *mainHello
= helloMessage
.rawContent() + 5;
417 assert((size_t)ssl
->init_buf
->max
> mainHelloSize
);
418 memcpy(ssl
->init_buf
->data
, mainHello
, mainHelloSize
);
419 debugs(83, 5, "Hello Data init and adjustd sizes :" << ssl
->init_num
<< " = "<< mainHelloSize
);
420 ssl
->init_num
= mainHelloSize
;
421 ssl
->s3
->wpend_ret
= mainHelloSize
;
422 ssl
->s3
->wpend_tot
= mainHelloSize
;
430 Ssl::ServerBio::write(const char *buf
, int size
, BIO
*table
)
434 debugs(83, 7, "postpone writing " << size
<< " bytes to SSL FD " << fd_
);
435 BIO_set_retry_write(table
);
439 if (!helloBuild
&& (bumpMode_
== Ssl::bumpPeek
|| bumpMode_
== Ssl::bumpStare
)) {
441 buf
[1] >= 3 //it is an SSL Version3 message
442 && buf
[0] == 0x16 // and it is a Handshake/Hello message
445 //Hello message is the first message we write to server
446 assert(helloMsg
.isEmpty());
448 auto ssl
= fd_table
[fd_
].ssl
.get();
450 if (bumpMode_
== Ssl::bumpPeek
) {
451 if (adjustSSL(ssl
, clientTlsDetails
, clientHelloMessage
))
454 helloMsg
.append(clientHelloMessage
);
455 debugs(83, 7, "SSL HELLO message for FD " << fd_
<< ": Random number is adjusted for peek mode");
456 } else { /*Ssl::bumpStare*/
458 if (adjustSSL(ssl
, clientTlsDetails
, clientHelloMessage
)) {
460 helloMsg
.append(clientHelloMessage
);
461 debugs(83, 7, "SSL HELLO message for FD " << fd_
<< ": Random number is adjusted for stare mode");
466 // If we do not build any hello message, copy the current
467 if (helloMsg
.isEmpty())
468 helloMsg
.append(buf
, size
);
471 helloMsgSize
= helloMsg
.length();
475 // Do not write yet.....
476 BIO_set_retry_write(table
);
481 if (!helloMsg
.isEmpty()) {
482 debugs(83, 7, "buffered write for FD " << fd_
);
483 int ret
= Ssl::Bio::write(helloMsg
.rawContent(), helloMsg
.length(), table
);
484 helloMsg
.consume(ret
);
485 if (!helloMsg
.isEmpty()) {
486 // We need to retry sendind data.
487 // Say to openSSL to retry sending hello message
488 BIO_set_retry_write(table
);
492 // Sending hello message complete. Do not send more data for now...
495 // spoof openSSL that we write what it ask us to write
498 return Ssl::Bio::write(buf
, size
, table
);
502 Ssl::ServerBio::flush(BIO
*table
)
504 if (!helloMsg
.isEmpty()) {
505 int ret
= Ssl::Bio::write(helloMsg
.rawContent(), helloMsg
.length(), table
);
506 helloMsg
.consume(ret
);
511 Ssl::ServerBio::resumingSession()
513 return parser_
.resumingSession
;
516 /// initializes BIO table after allocation
518 squid_bio_create(BIO
*bi
)
520 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
521 bi
->init
= 0; // set when we store Bio object and socket fd (BIO_C_SET_FD)
525 // No need to set more, openSSL initialize BIO memory to zero.
528 BIO_set_data(bi
, NULL
);
532 /// cleans BIO table before deallocation
534 squid_bio_destroy(BIO
*table
)
536 delete static_cast<Ssl::Bio
*>(BIO_get_data(table
));
537 BIO_set_data(table
, NULL
);
541 /// wrapper for Bio::write()
543 squid_bio_write(BIO
*table
, const char *buf
, int size
)
545 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(BIO_get_data(table
));
547 return bio
->write(buf
, size
, table
);
550 /// wrapper for Bio::read()
552 squid_bio_read(BIO
*table
, char *buf
, int size
)
554 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(BIO_get_data(table
));
556 return bio
->read(buf
, size
, table
);
559 /// implements puts() via write()
561 squid_bio_puts(BIO
*table
, const char *str
)
564 return squid_bio_write(table
, str
, strlen(str
));
567 /// other BIO manipulations (those without dedicated callbacks in BIO table)
569 squid_bio_ctrl(BIO
*table
, int cmd
, long arg1
, void *arg2
)
571 debugs(83, 5, table
<< ' ' << cmd
<< '(' << arg1
<< ", " << arg2
<< ')');
576 const int fd
= *static_cast<int*>(arg2
);
578 if (arg1
== Ssl::Bio::BIO_TO_SERVER
)
579 bio
= new Ssl::ServerBio(fd
);
581 bio
= new Ssl::ClientBio(fd
);
582 assert(!BIO_get_data(table
));
583 BIO_set_data(table
, bio
);
584 BIO_set_init(table
, 1);
589 if (BIO_get_init(table
)) {
590 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(BIO_get_data(table
));
593 *static_cast<int*>(arg2
) = bio
->fd();
599 // Should implemented if the SSL_dup openSSL API function
600 // used anywhere in squid.
604 if (BIO_get_init(table
)) {
605 Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(BIO_get_data(table
));
612 /* we may also need to implement these:
614 case BIO_C_FILE_SEEK:
615 case BIO_C_FILE_TELL:
617 case BIO_CTRL_GET_CLOSE:
618 case BIO_CTRL_SET_CLOSE:
619 case BIO_CTRL_PENDING:
620 case BIO_CTRL_WPENDING:
627 return 0; /* NOTREACHED */
630 /// wrapper for Bio::stateChanged()
632 squid_ssl_info(const SSL
*ssl
, int where
, int ret
)
634 if (BIO
*table
= SSL_get_rbio(ssl
)) {
635 if (Ssl::Bio
*bio
= static_cast<Ssl::Bio
*>(BIO_get_data(table
)))
636 bio
->stateChanged(ssl
, where
, ret
);
641 applyTlsDetailsToSSL(SSL
*ssl
, Security::TlsDetails::Pointer
const &details
, Ssl::BumpMode bumpMode
)
643 // To increase the possibility for bumping after peek mode selection or
644 // splicing after stare mode selection it is good to set the
645 // SSL protocol version.
646 // The SSL_set_ssl_method is wrong here because it will restrict the
647 // permitted transport version to be identical to the version used in the
648 // ClientHello message.
649 // For example will prevent comunnicating with a tls1.0 server if the
650 // client sent and tlsv1.2 Hello message.
651 #if defined(TLSEXT_NAMETYPE_host_name)
652 if (!details
->serverName
.isEmpty()) {
653 SSL_set_tlsext_host_name(ssl
, details
->serverName
.c_str());
657 if (!details
->ciphers
.empty()) {
659 for (auto cipherId
: details
->ciphers
) {
660 unsigned char cbytes
[3];
661 cbytes
[0] = (cipherId
>> 8) & 0xFF;
662 cbytes
[1] = cipherId
& 0xFF;
664 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
665 const SSL_METHOD
*method
= SSLv23_method();
666 const SSL_CIPHER
*c
= method
->get_cipher_by_char(cbytes
);
668 const SSL_CIPHER
*c
= SSL_CIPHER_find(ssl
, cbytes
);
671 if (!strCiphers
.isEmpty())
672 strCiphers
.append(":");
673 strCiphers
.append(SSL_CIPHER_get_name(c
));
676 if (!strCiphers
.isEmpty())
677 SSL_set_cipher_list(ssl
, strCiphers
.c_str());
680 #if defined(SSL_OP_NO_COMPRESSION) /* XXX: OpenSSL 0.9.8k lacks SSL_OP_NO_COMPRESSION */
681 if (!details
->compressionSupported
)
682 SSL_set_options(ssl
, SSL_OP_NO_COMPRESSION
);
685 #if defined(TLSEXT_STATUSTYPE_ocsp)
686 if (details
->tlsStatusRequest
)
687 SSL_set_tlsext_status_type(ssl
, TLSEXT_STATUSTYPE_ocsp
);
690 #if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
691 if (!details
->tlsAppLayerProtoNeg
.isEmpty()) {
692 if (bumpMode
== Ssl::bumpPeek
)
693 SSL_set_alpn_protos(ssl
, (const unsigned char*)details
->tlsAppLayerProtoNeg
.rawContent(), details
->tlsAppLayerProtoNeg
.length());
695 static const unsigned char supported_protos
[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
696 SSL_set_alpn_protos(ssl
, supported_protos
, sizeof(supported_protos
));
702 #endif // USE_OPENSSL