27extern int socket_read_method(
int,
char *,
int);
28extern int socket_write_method(
int,
const char *,
int);
42#if HAVE_LIBCRYPTO_BIO_METH_NEW
64#if HAVE_LIBCRYPTO_BIO_METH_NEW
80 if (BIO *bio = BIO_new(useMethod)) {
81 BIO_int_ctrl(bio, BIO_C_SET_FD, type,
fd);
90 SSL_set_bio(ssl, bio, bio);
96 debugs(83, 7,
"Bio constructed, this=" <<
this <<
" FD " <<
fd_);
101 debugs(83, 7,
"Bio destructing, this=" <<
this <<
" FD " << fd_);
108 const int result = socket_write_method(fd_, buf,
size);
112 const int xerrno = errno;
113 debugs(83, 5,
"FD " << fd_ <<
" wrote " << result <<
" <= " <<
size);
115 BIO_clear_retry_flags(table);
118 debugs(83, 5,
"error: " << xerrno <<
" ignored: " << ignoreError);
120 BIO_set_retry_write(table);
131 const int result = socket_read_method(fd_, buf,
size);
135 const int xerrno = errno;
136 debugs(83, 5,
"FD " << fd_ <<
" read " << result <<
" <= " <<
size);
138 BIO_clear_retry_flags(table);
141 debugs(83, 5,
"error: " << xerrno <<
" ignored: " << ignoreError);
143 BIO_set_retry_read(table);
163 debugs(83, 7,
"FD " << fd_ <<
" now: 0x" << std::hex << where << std::dec <<
' ' <<
164 SSL_state_string(ssl) <<
" (" << SSL_state_string_long(ssl) <<
")");
181 if (where & SSL_CB_HANDSHAKE_START) {
182 const int reneg = renegotiations.count(1);
187 if (reneg > RenegotiationsLimit) {
188 abortReason =
"renegotiate requests flood";
189 debugs(83,
DBG_IMPORTANT,
"Terminating TLS connection [from " <<
fd_table[fd_].ipaddr <<
"] due to " << abortReason <<
". This connection received " <<
190 reneg <<
" renegotiate requests in the last " <<
191 RenegotiationsWindow <<
" seconds (and " <<
192 renegotiations.remembered() <<
" requests total).");
201 debugs(83, 3,
"BIO on FD " << fd_ <<
" is aborted");
202 BIO_clear_retry_flags(table);
207 BIO_set_retry_write(table);
218 debugs(83, 3,
"BIO on FD " << fd_ <<
" is aborted");
219 BIO_clear_retry_flags(table);
224 debugs(83, 7,
"Hold flag is set, retry latter. (Hold " <<
size <<
"bytes)");
225 BIO_set_retry_read(table);
229 if (!rbuf.isEmpty()) {
230 int bytes = (
size <= (
int)rbuf.length() ?
size : rbuf.length());
231 memcpy(buf, rbuf.rawContent(), bytes);
248 parsedHandshake(false),
252 parser_(
Security::HandshakeParser::fromServer)
265 clientTlsDetails = details;
266 clientSentHello = aHello;
273 return readAndGive(buf,
size, table);
275 return readAndParse(buf,
size, table);
284 if (rbufConsumePos < rbuf.length())
285 return giveBuffered(buf,
size);
288 const int result = readAndBuffer(table);
291 return giveBuffered(buf,
size);
302 const int result = readAndBuffer(table);
307 if (!parser_.parseHello(rbuf)) {
309 BIO_set_retry_read(table);
312 parsedHandshake =
true;
314 catch (
const std::exception &ex) {
315 debugs(83, 2,
"parsing error on FD " << fd_ <<
": " << ex.what());
316 parsedHandshake =
true;
320 return giveBuffered(buf,
size);
328 char *space = rbuf.rawAppendStart(SQUID_TCP_SO_RCVBUF);
329 const int result =
Ssl::Bio::read(space, SQUID_TCP_SO_RCVBUF, table);
333 rbuf.rawAppendFinish(space, result);
342 if (rbuf.length() <= rbufConsumePos)
345 const int unsent = rbuf.length() - rbufConsumePos;
346 const int bytes = (
size <= unsent ?
size : unsent);
347 memcpy(buf, rbuf.rawContent() + rbufConsumePos, bytes);
348 rbufConsumePos += bytes;
349 debugs(83, 7, bytes <<
"<=" <<
size <<
" bytes to OpenSSL");
358 debugs(83, 7,
"postpone writing " <<
size <<
" bytes to SSL FD " << fd_);
359 BIO_set_retry_write(table);
369 debugs(83, 7,
"to-server" <<
Raw(
"TLSPlaintext", buf,
size).hex());
372 Must(20 <= buf[0] && buf[0] <= 23);
375 assert(helloMsg.isEmpty());
379 Must(!clientSentHello.isEmpty());
382 helloMsg.append(clientSentHello);
383 debugs(83, 7,
"FD " << fd_ <<
": Using client-sent ClientHello for peek mode");
389 if (helloMsg.isEmpty())
390 helloMsg.append(buf,
size);
393 helloMsgSize = helloMsg.length();
397 BIO_set_retry_write(table);
402 if (!helloMsg.isEmpty()) {
403 debugs(83, 7,
"buffered write for FD " << fd_);
404 int ret =
Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
405 helloMsg.consume(ret);
406 if (!helloMsg.isEmpty()) {
409 BIO_set_retry_write(table);
425 if (!helloMsg.isEmpty()) {
426 int ret =
Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
427 helloMsg.consume(ret);
434 return parser_.resumingSession;
440 return parser_.details->tlsSupportedVersion &&
448#if !HAVE_LIBCRYPTO_BIO_GET_INIT
499 debugs(83, 5, table <<
' ' << cmd <<
'(' << arg1 <<
", " << arg2 <<
')');
504 const int fd = *
static_cast<int*
>(arg2);
521 *
static_cast<int*
>(arg2) = bio->
fd();
562 if (BIO *table = SSL_get_rbio(ssl)) {
564 bio->stateChanged(ssl, where, ret);
579#if defined(TLSEXT_NAMETYPE_host_name)
580 if (!details->serverName.isEmpty()) {
581 SSL_set_tlsext_host_name(ssl, details->serverName.c_str());
585 if (!details->ciphers.empty()) {
587 for (
auto cipherId: details->ciphers) {
588 unsigned char cbytes[3];
589 cbytes[0] = (cipherId >> 8) & 0xFF;
590 cbytes[1] = cipherId & 0xFF;
595 strCiphers.
append(SSL_CIPHER_get_name(c));
599 SSL_set_cipher_list(ssl, strCiphers.
c_str());
602#if defined(SSL_OP_NO_COMPRESSION)
603 if (!details->compressionSupported)
604 SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
607#if defined(SSL_OP_NO_TLSv1_3)
610 SSL_set_options(ssl, SSL_OP_NO_TLSv1_3);
613#if defined(TLSEXT_STATUSTYPE_ocsp)
614 if (details->tlsStatusRequest)
615 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
618#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
619 if (!details->tlsAppLayerProtoNeg.isEmpty()) {
621 SSL_set_alpn_protos(ssl, (
const unsigned char*)details->tlsAppLayerProtoNeg.rawContent(), details->tlsAppLayerProtoNeg.length());
623 static const unsigned char supported_protos[] = {8,
'h',
't',
't',
'p',
'/',
'1',
'.',
'1'};
624 SSL_set_alpn_protos(ssl, supported_protos,
sizeof(supported_protos));
static int squid_bio_puts(BIO *h, const char *str)
implements puts() via write()
static void squid_ssl_info(const SSL *ssl, int where, int ret)
wrapper for Bio::stateChanged()
static int squid_bio_create(BIO *h)
initializes BIO table after allocation
static int squid_bio_write(BIO *h, const char *buf, int num)
wrapper for Bio::write()
static int squid_bio_destroy(BIO *data)
cleans BIO table before deallocation
void applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode)
static BIO_METHOD SquidMethods
static long squid_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2)
other BIO manipulations (those without dedicated callbacks in BIO table)
static int squid_bio_read(BIO *h, char *buf, int size)
wrapper for Bio::read()
void configure(double horizonSeconds)
0=remember nothing; -1=forget nothing; new value triggers clear()
SBuf & append(const SBuf &S)
BIO source and sink node, handling socket I/O and monitoring SSL state.
int fd() const
The SSL socket descriptor.
const int fd_
the SSL socket we are reading and writing
virtual void stateChanged(const SSL *ssl, int where, int ret)
virtual int write(const char *buf, int size, BIO *table)
Writes the given data to socket.
static void Link(SSL *ssl, BIO *bio)
Tells ssl connection to use BIO and monitor state via stateChanged()
static BIO * Create(const int fd, Security::Io::Type type)
virtual void flush(BIO *)
virtual int read(char *buf, int size, BIO *table)
Reads data from socket.
FadingCounter renegotiations
client requested renegotiations limit control
int write(const char *buf, int size, BIO *table) override
The ClientBio version of the Ssl::Bio::write method.
void stateChanged(const SSL *ssl, int where, int ret) override
ClientBio(const int anFd)
int read(char *buf, int size, BIO *table) override
int write(const char *buf, int size, BIO *table) override
void flush(BIO *table) override
ServerBio(const int anFd)
void setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &hello)
Sets the random number to use in client SSL HELLO message.
void stateChanged(const SSL *ssl, int where, int ret) override
The ServerBio version of the Ssl::Bio::stateChanged method.
bool encryptedCertificates() const
int readAndParse(char *buf, const int size, BIO *table)
int read(char *buf, int size, BIO *table) override
int readAndGive(char *buf, const int size, BIO *table)
Read and give everything to OpenSSL.
int readAndBuffer(BIO *table)
int giveBuffered(char *buf, const int size)
int ignoreErrno(int ierrno)
#define debugs(SECTION, LEVEL, CONTENT)
int default_read_method(int, char *, int)
int default_write_method(int, const char *, int)
const char * bumpMode(int bm)
Network/connection security abstraction layer.
bool Tls1p3orLater(const AnyP::ProtocolVersion &p)
whether the given TLS/SSL protocol is TLS v1.3 or later
bool Tls1p2orEarlier(const AnyP::ProtocolVersion &p)
whether the given TLS/SSL protocol is TLS v1.2 or earlier, including SSL
const SSL_CIPHER * SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr)
void * BIO_get_data(BIO *table)
void BIO_set_init(BIO *table, int init)
void BIO_set_data(BIO *table, void *data)
int BIO_get_init(BIO *table)