bio.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2020 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 static BIO_METHOD SquidMethods = {
48  BIO_TYPE_SOCKET,
49  "squid",
53  NULL, // squid_bio_gets not supported
57  NULL // squid_callback_ctrl not supported
58 };
59 #endif
60 
61 BIO *
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 
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 
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 
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 
242  Bio(anFd),
243  helloMsgSize(0),
244  helloBuild(false),
245  allowSplice(false),
246  allowBump(false),
247  holdWrite_(false),
248  holdRead_(true),
249  record_(false),
250  parsedHandshake(false),
251  parseError(false),
252  bumpMode_(bumpNone),
253  rbufConsumePos(0),
254  parser_(Security::HandshakeParser::fromServer)
255 {
256 }
257 
258 void
259 Ssl::ServerBio::stateChanged(const SSL *ssl, int where, int ret)
260 {
261  Ssl::Bio::stateChanged(ssl, where, ret);
262 }
263 
264 void
266 {
267  clientTlsDetails = details;
268  clientSentHello = aHello;
269 };
270 
271 int
272 Ssl::ServerBio::read(char *buf, int size, BIO *table)
273 {
274  if (parsedHandshake) // done parsing TLS Hello
275  return readAndGive(buf, size, table);
276  else
277  return readAndParse(buf, size, table);
278 }
279 
281 int
282 Ssl::ServerBio::readAndGive(char *buf, const int size, BIO *table)
283 {
284  // If we have unused buffered bytes, give those bytes to OpenSSL now,
285  // before reading more. TODO: Read if we have buffered less than size?
286  if (rbufConsumePos < rbuf.length())
287  return giveBuffered(buf, size);
288 
289  if (record_) {
290  const int result = readAndBuffer(table);
291  if (result <= 0)
292  return result;
293  return giveBuffered(buf, size);
294  }
295 
296  return Ssl::Bio::read(buf, size, table);
297 }
298 
301 int
302 Ssl::ServerBio::readAndParse(char *buf, const int size, BIO *table)
303 {
304  const int result = readAndBuffer(table);
305  if (result <= 0)
306  return result;
307 
308  try {
309  if (!parser_.parseHello(rbuf)) {
310  // need more data to finish parsing
311  BIO_set_retry_read(table);
312  return -1;
313  }
314  parsedHandshake = true; // done parsing (successfully)
315  }
316  catch (const std::exception &ex) {
317  debugs(83, 2, "parsing error on FD " << fd_ << ": " << ex.what());
318  parsedHandshake = true; // done parsing (due to an error)
319  parseError = true;
320  }
321 
322  if (holdRead_) {
323  debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
324  BIO_set_retry_read(table);
325  return -1;
326  }
327 
328  return giveBuffered(buf, size);
329 }
330 
333 int
335 {
336  char *space = rbuf.rawAppendStart(SQUID_TCP_SO_RCVBUF);
337  const int result = Ssl::Bio::read(space, SQUID_TCP_SO_RCVBUF, table);
338  if (result <= 0)
339  return result;
340 
341  rbuf.rawAppendFinish(space, result);
342  return result;
343 }
344 
347 int
349 {
350  if (rbuf.length() <= rbufConsumePos)
351  return -1; // buffered nothing yet
352 
353  const int unsent = rbuf.length() - rbufConsumePos;
354  const int bytes = (size <= unsent ? size : unsent);
355  memcpy(buf, rbuf.rawContent() + rbufConsumePos, bytes);
356  rbufConsumePos += bytes;
357  debugs(83, 7, bytes << "<=" << size << " bytes to OpenSSL");
358  return bytes;
359 }
360 
361 // This function makes the required checks to examine if the client hello
362 // message is compatible with the features provided by OpenSSL toolkit.
363 // If the features are compatible and can be supported it tries to rewrite SSL
364 // structure members, to replace the hello message created by openSSL, with the
365 // web client SSL hello message.
366 // This is mostly possible in the cases where the web client uses openSSL
367 // library similar with this one used by squid.
368 static bool
369 adjustSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, SBuf &helloMessage)
370 {
371 #if SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK
372  if (!details)
373  return false;
374 
375  if (!ssl->s3) {
376  debugs(83, 5, "No SSLv3 data found!");
377  return false;
378  }
379 
380  // If the client supports compression but our context does not support
381  // we can not adjust.
382 #if !defined(OPENSSL_NO_COMP)
383  const bool requireCompression = (details->compressionSupported && ssl->ctx->comp_methods == nullptr);
384 #else
385  const bool requireCompression = details->compressionSupported;
386 #endif
387  if (requireCompression) {
388  debugs(83, 5, "Client Hello Data supports compression, but we do not!");
389  return false;
390  }
391 
392 #if !defined(SSL_TLSEXT_HB_ENABLED)
393  if (details->doHeartBeats) {
394  debugs(83, 5, "Client Hello Data supports HeartBeats but we do not support!");
395  return false;
396  }
397 #endif
398 
399  if (details->unsupportedExtensions) {
400  debugs(83, 5, "Client Hello contains extensions that we do not support!");
401  return false;
402  }
403 
404  SSL3_BUFFER *wb=&(ssl->s3->wbuf);
405  if (wb->len < (size_t)helloMessage.length()) {
406  debugs(83, 5, "Client Hello exceeds OpenSSL buffer: " << helloMessage.length() << " >= " << wb->len);
407  return false;
408  }
409 
410  /* Check whether all on-the-wire ciphers are supported by OpenSSL. */
411 
412  const auto &wireCiphers = details->ciphers;
413  Security::TlsDetails::Ciphers::size_type ciphersToFind = wireCiphers.size();
414 
415  // RFC 5746: "TLS_EMPTY_RENEGOTIATION_INFO_SCSV is not a true cipher suite".
416  // It is commonly seen on the wire, including in from-OpenSSL traffic, but
417  // SSL_get_ciphers() does not return this _pseudo_ cipher suite in my tests.
418  // If OpenSSL supports scsvCipher, we count it (at most once) further below.
419 #if defined(TLSEXT_TYPE_renegotiate)
420  // the 0x00FFFF mask converts 3-byte OpenSSL cipher to our 2-byte cipher
421  const uint16_t scsvCipher = SSL3_CK_SCSV & 0x00FFFF;
422 #else
423  const uint16_t scsvCipher = 0;
424 #endif
425 
426  STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(ssl);
427  const int supportedCipherCount = sk_SSL_CIPHER_num(cipher_stack);
428  for (int idx = 0; idx < supportedCipherCount && ciphersToFind > 0; ++idx) {
429  const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(cipher_stack, idx);
430  const auto id = SSL_CIPHER_get_id(cipher) & 0x00FFFF;
431  if (wireCiphers.find(id) != wireCiphers.end() && (!scsvCipher || id != scsvCipher))
432  --ciphersToFind;
433  }
434 
435  if (ciphersToFind > 0 && scsvCipher && wireCiphers.find(scsvCipher) != wireCiphers.end())
436  --ciphersToFind;
437 
438  if (ciphersToFind > 0) {
439  // TODO: Add slowlyReportUnsupportedCiphers() to slowly find and report each of them
440  debugs(83, 5, "Client Hello Data has " << ciphersToFind << " ciphers that we do not support!");
441  return false;
442  }
443 
444  debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
445 
446  //Adjust ssl structure data.
447  // We need to fix the random in SSL struct:
448  if (details->clientRandom.length() == SSL3_RANDOM_SIZE)
449  memcpy(ssl->s3->client_random, details->clientRandom.c_str(), SSL3_RANDOM_SIZE);
450  memcpy(wb->buf, helloMessage.rawContent(), helloMessage.length());
451  wb->left = helloMessage.length();
452 
453  size_t mainHelloSize = helloMessage.length() - 5;
454  const char *mainHello = helloMessage.rawContent() + 5;
455  assert((size_t)ssl->init_buf->max > mainHelloSize);
456  memcpy(ssl->init_buf->data, mainHello, mainHelloSize);
457  debugs(83, 5, "Hello Data init and adjustd sizes :" << ssl->init_num << " = "<< mainHelloSize);
458  ssl->init_num = mainHelloSize;
459  ssl->s3->wpend_ret = mainHelloSize;
460  ssl->s3->wpend_tot = mainHelloSize;
461  return true;
462 #else
463  return false;
464 #endif
465 }
466 
467 int
468 Ssl::ServerBio::write(const char *buf, int size, BIO *table)
469 {
470 
471  if (holdWrite_) {
472  debugs(83, 7, "postpone writing " << size << " bytes to SSL FD " << fd_);
473  BIO_set_retry_write(table);
474  return -1;
475  }
476 
477  if (!helloBuild && (bumpMode_ == Ssl::bumpPeek || bumpMode_ == Ssl::bumpStare)) {
478  // buf contains OpenSSL-generated ClientHello. We assume it has a
479  // complete ClientHello and nothing else, but cannot fully verify
480  // that quickly. We only verify that buf starts with a v3+ record
481  // containing ClientHello.
482  Must(size >= 2); // enough for version and content_type checks below
483  Must(buf[1] >= 3); // record's version.major; determines buf[0] meaning
484  Must(buf[0] == 22); // TLSPlaintext.content_type == handshake in v3+
485 
486  //Hello message is the first message we write to server
487  assert(helloMsg.isEmpty());
488 
489  if (auto ssl = fd_table[fd_].ssl.get()) {
490  if (bumpMode_ == Ssl::bumpPeek) {
491  // we should not be here if we failed to parse the client-sent ClientHello
492  Must(!clientSentHello.isEmpty());
493  if (adjustSSL(ssl, clientTlsDetails, clientSentHello))
494  allowBump = true;
495  allowSplice = true;
496  // Replace OpenSSL-generated ClientHello with client-sent one.
497  helloMsg.append(clientSentHello);
498  debugs(83, 7, "FD " << fd_ << ": Using client-sent ClientHello for peek mode");
499  } else { /*Ssl::bumpStare*/
500  allowBump = true;
501  if (!clientSentHello.isEmpty() && adjustSSL(ssl, clientTlsDetails, clientSentHello)) {
502  allowSplice = true;
503  helloMsg.append(clientSentHello);
504  debugs(83, 7, "FD " << fd_ << ": Using client-sent ClientHello for stare mode");
505  }
506  }
507  }
508  // if we did not use the client-sent ClientHello, then use the OpenSSL-generated one
509  if (helloMsg.isEmpty())
510  helloMsg.append(buf, size);
511 
512  helloBuild = true;
513  helloMsgSize = helloMsg.length();
514  //allowBump = true;
515 
516  if (allowSplice) {
517  // Do not write yet.....
518  BIO_set_retry_write(table);
519  return -1;
520  }
521  }
522 
523  if (!helloMsg.isEmpty()) {
524  debugs(83, 7, "buffered write for FD " << fd_);
525  int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
526  helloMsg.consume(ret);
527  if (!helloMsg.isEmpty()) {
528  // We need to retry sendind data.
529  // Say to openSSL to retry sending hello message
530  BIO_set_retry_write(table);
531  return -1;
532  }
533 
534  // Sending hello message complete. Do not send more data for now...
535  holdWrite_ = true;
536 
537  // spoof openSSL that we write what it ask us to write
538  return size;
539  } else
540  return Ssl::Bio::write(buf, size, table);
541 }
542 
543 void
545 {
546  if (!helloMsg.isEmpty()) {
547  int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
548  helloMsg.consume(ret);
549  }
550 }
551 
552 bool
554 {
555  return parser_.resumingSession;
556 }
557 
558 bool
560 {
561  return parser_.details->tlsSupportedVersion &&
562  Security::Tls1p3orLater(parser_.details->tlsSupportedVersion);
563 }
564 
566 static int
568 {
569 #if !HAVE_LIBCRYPTO_BIO_GET_INIT
570  bi->init = 0; // set when we store Bio object and socket fd (BIO_C_SET_FD)
571  bi->num = 0;
572  bi->flags = 0;
573 #else
574  // No need to set more, openSSL initialize BIO memory to zero.
575 #endif
576 
577  BIO_set_data(bi, NULL);
578  return 1;
579 }
580 
582 static int
583 squid_bio_destroy(BIO *table)
584 {
585  delete static_cast<Ssl::Bio*>(BIO_get_data(table));
586  BIO_set_data(table, NULL);
587  return 1;
588 }
589 
591 static int
592 squid_bio_write(BIO *table, const char *buf, int size)
593 {
594  Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
595  assert(bio);
596  return bio->write(buf, size, table);
597 }
598 
600 static int
601 squid_bio_read(BIO *table, char *buf, int size)
602 {
603  Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
604  assert(bio);
605  return bio->read(buf, size, table);
606 }
607 
609 static int
610 squid_bio_puts(BIO *table, const char *str)
611 {
612  assert(str);
613  return squid_bio_write(table, str, strlen(str));
614 }
615 
617 static long
618 squid_bio_ctrl(BIO *table, int cmd, long arg1, void *arg2)
619 {
620  debugs(83, 5, table << ' ' << cmd << '(' << arg1 << ", " << arg2 << ')');
621 
622  switch (cmd) {
623  case BIO_C_SET_FD: {
624  assert(arg2);
625  const int fd = *static_cast<int*>(arg2);
626  Ssl::Bio *bio;
627  if (arg1 == Security::Io::BIO_TO_SERVER)
628  bio = new Ssl::ServerBio(fd);
629  else
630  bio = new Ssl::ClientBio(fd);
631  assert(!BIO_get_data(table));
632  BIO_set_data(table, bio);
633  BIO_set_init(table, 1);
634  return 0;
635  }
636 
637  case BIO_C_GET_FD:
638  if (BIO_get_init(table)) {
639  Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
640  assert(bio);
641  if (arg2)
642  *static_cast<int*>(arg2) = bio->fd();
643  return bio->fd();
644  }
645  return -1;
646 
647  case BIO_CTRL_DUP:
648  // Should implemented if the SSL_dup openSSL API function
649  // used anywhere in squid.
650  return 0;
651 
652  case BIO_CTRL_FLUSH:
653  if (BIO_get_init(table)) {
654  Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
655  assert(bio);
656  bio->flush(table);
657  return 1;
658  }
659  return 0;
660 
661  /* we may also need to implement these:
662  case BIO_CTRL_RESET:
663  case BIO_C_FILE_SEEK:
664  case BIO_C_FILE_TELL:
665  case BIO_CTRL_INFO:
666  case BIO_CTRL_GET_CLOSE:
667  case BIO_CTRL_SET_CLOSE:
668  case BIO_CTRL_PENDING:
669  case BIO_CTRL_WPENDING:
670  */
671  default:
672  return 0;
673 
674  }
675 
676  return 0; /* NOTREACHED */
677 }
678 
680 static void
681 squid_ssl_info(const SSL *ssl, int where, int ret)
682 {
683  if (BIO *table = SSL_get_rbio(ssl)) {
684  if (Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table)))
685  bio->stateChanged(ssl, where, ret);
686  }
687 }
688 
689 void
691 {
692  // To increase the possibility for bumping after peek mode selection or
693  // splicing after stare mode selection it is good to set the
694  // SSL protocol version.
695  // The SSL_set_ssl_method is wrong here because it will restrict the
696  // permitted transport version to be identical to the version used in the
697  // ClientHello message.
698  // For example will prevent comunnicating with a tls1.0 server if the
699  // client sent and tlsv1.2 Hello message.
700 #if defined(TLSEXT_NAMETYPE_host_name)
701  if (!details->serverName.isEmpty()) {
702  SSL_set_tlsext_host_name(ssl, details->serverName.c_str());
703  }
704 #endif
705 
706  if (!details->ciphers.empty()) {
707  SBuf strCiphers;
708  for (auto cipherId: details->ciphers) {
709  unsigned char cbytes[3];
710  cbytes[0] = (cipherId >> 8) & 0xFF;
711  cbytes[1] = cipherId & 0xFF;
712  cbytes[2] = 0;
713  if (const auto c = SSL_CIPHER_find(ssl, cbytes)) {
714  if (!strCiphers.isEmpty())
715  strCiphers.append(":");
716  strCiphers.append(SSL_CIPHER_get_name(c));
717  }
718  }
719  if (!strCiphers.isEmpty())
720  SSL_set_cipher_list(ssl, strCiphers.c_str());
721  }
722 
723 #if defined(SSL_OP_NO_COMPRESSION) /* XXX: OpenSSL 0.9.8k lacks SSL_OP_NO_COMPRESSION */
724  if (!details->compressionSupported)
725  SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
726 #endif
727 
728 #if defined(SSL_OP_NO_TLSv1_3)
729  // avoid "inappropriate fallback" OpenSSL error messages
730  if (details->tlsSupportedVersion && Security::Tls1p2orEarlier(details->tlsSupportedVersion))
731  SSL_set_options(ssl, SSL_OP_NO_TLSv1_3);
732 #endif
733 
734 #if defined(TLSEXT_STATUSTYPE_ocsp)
735  if (details->tlsStatusRequest)
736  SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
737 #endif
738 
739 #if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
740  if (!details->tlsAppLayerProtoNeg.isEmpty()) {
741  if (bumpMode == Ssl::bumpPeek)
742  SSL_set_alpn_protos(ssl, (const unsigned char*)details->tlsAppLayerProtoNeg.rawContent(), details->tlsAppLayerProtoNeg.length());
743  else {
744  static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
745  SSL_set_alpn_protos(ssl, supported_protos, sizeof(supported_protos));
746  }
747  }
748 #endif
749 }
750 
751 #endif // USE_OPENSSL
752 
@ bumpPeek
Definition: support.h:136
static void Link(SSL *ssl, BIO *bio)
Tells ssl connection to use BIO and monitor state via stateChanged()
Definition: bio.cc:88
static int squid_bio_create(BIO *h)
initializes BIO table after allocation
Definition: bio.cc:567
void setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &hello)
Sets the random number to use in client SSL HELLO message.
Definition: bio.cc:265
bool isEmpty() const
Definition: SBuf.h:420
void configure(double horizonSeconds)
0=remember nothing; -1=forget nothing; new value triggers clear()
void applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode)
Definition: bio.cc:690
const SSL_CIPHER * SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr)
Definition: openssl.h:137
virtual ~Bio()
Definition: bio.cc:99
Definition: SBuf.h:86
BumpMode
Definition: support.h:136
virtual void stateChanged(const SSL *ssl, int where, int ret)
Definition: bio.cc:152
int const char int
Definition: stub_libmem.cc:75
static bool adjustSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, SBuf &helloMessage)
Definition: bio.cc:369
ClientBio(const int anFd)
Definition: bio.cc:167
int type
Definition: errorpage.cc:152
int readAndGive(char *buf, const int size, BIO *table)
Read and give everything to OpenSSL.
Definition: bio.cc:282
void * BIO_get_data(BIO *table)
Definition: openssl.h:60
#define DBG_IMPORTANT
Definition: Debug.h:46
virtual int write(const char *buf, int size, BIO *table)
Definition: bio.cc:468
ServerBio(const int anFd)
Definition: bio.cc:241
@ BIO_TO_SERVER
Definition: forward.h:116
int BIO_get_init(BIO *table)
Definition: openssl.h:80
static BIO * Create(const int fd, Security::Io::Type type)
Definition: bio.cc:62
virtual int read(char *buf, int size, BIO *table)
Definition: bio.cc:272
void BIO_set_data(BIO *table, void *data)
Definition: openssl.h:66
int size
Definition: ModDevPoll.cc:77
#define NULL
Definition: types.h:166
const char * rawContent() const
Definition: SBuf.cc:519
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:128
virtual int read(char *buf, int size, BIO *table)
Reads data from socket.
Definition: bio.cc:127
bool Tls1p2orEarlier(const AnyP::ProtocolVersion &p)
whether the given TLS/SSL protocol is TLS v1.2 or earlier, including SSL
Definition: Handshake.h:156
virtual int write(const char *buf, int size, BIO *table)
The ClientBio version of the Ssl::Bio::write method.
Definition: bio.cc:199
#define true
Definition: GnuRegex.c:234
int default_read_method(int, char *, int)
Definition: fd.cc:146
int readAndBuffer(BIO *table)
Definition: bio.cc:334
virtual int write(const char *buf, int size, BIO *table)
Writes the given data to socket.
Definition: bio.cc:104
static int squid_bio_puts(BIO *h, const char *str)
implements puts() via write()
Definition: bio.cc:610
virtual void stateChanged(const SSL *ssl, int where, int ret)
The ServerBio version of the Ssl::Bio::stateChanged method.
Definition: bio.cc:259
void const char HLPCB void * data
Definition: stub_helper.cc:16
#define assert(EX)
Definition: assert.h:19
static int squid_bio_destroy(BIO *data)
cleans BIO table before deallocation
Definition: bio.cc:583
bool resumingSession()
Definition: bio.cc:553
const char * c_str()
Definition: SBuf.cc:526
int default_write_method(int, const char *, int)
Definition: fd.cc:156
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:404
Bio(const int anFd)
Definition: bio.cc:94
SBuf & append(const SBuf &S)
Definition: SBuf.cc:195
bool Tls1p3orLater(const AnyP::ProtocolVersion &p)
whether the given TLS/SSL protocol is TLS v1.3 or later
Definition: Handshake.h:163
@ bumpStare
Definition: support.h:136
int ignoreErrno(int ierrno)
Definition: comm.cc:1507
#define fd_table
Definition: fde.h:189
BIO source and sink node, handling socket I/O and monitoring SSL state.
Definition: bio.h:33
static int squid_bio_read(BIO *h, char *buf, int size)
wrapper for Bio::read()
Definition: bio.cc:601
bool encryptedCertificates() const
Definition: bio.cc:559
const int fd_
the SSL socket we are reading and writing
Definition: bio.h:63
static long squid_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2)
other BIO manipulations (those without dedicated callbacks in BIO table)
Definition: bio.cc:618
FadingCounter renegotiations
client requested renegotiations limit control
Definition: bio.h:102
static int squid_bio_write(BIO *h, const char *buf, int num)
wrapper for Bio::write()
Definition: bio.cc:592
int giveBuffered(char *buf, const int size)
Definition: bio.cc:348
@ bumpNone
Definition: support.h:136
virtual int read(char *buf, int size, BIO *table)
Definition: bio.cc:216
virtual void stateChanged(const SSL *ssl, int where, int ret)
Definition: bio.cc:178
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:69
static void squid_ssl_info(const SSL *ssl, int where, int ret)
wrapper for Bio::stateChanged()
Definition: bio.cc:681
virtual void flush(BIO *table)
Definition: bio.h:47
int readAndParse(char *buf, const int size, BIO *table)
Definition: bio.cc:302
STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx)
Definition: openssl.h:195
void BIO_set_init(BIO *table, int init)
Definition: openssl.h:72
#define false
Definition: GnuRegex.c:233
Network/connection security abstraction layer.
Definition: Connection.h:33
const char * bumpMode(int bm)
Definition: support.h:148
void const char * buf
Definition: stub_helper.cc:16
static BIO_METHOD SquidMethods
Definition: bio.cc:47
virtual void flush(BIO *table)
Definition: bio.cc:544

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors