]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/bio.cc
Bug 4662: pt1: Feature detect the OpenSSL TLS_method() and similar functions
[thirdparty/squid.git] / src / ssl / bio.cc
CommitLineData
b3a8ae1b 1/*
4ac4a490 2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
b3a8ae1b 3 *
bbc27441
AJ
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.
b3a8ae1b
AR
7 */
8
bbc27441
AJ
9/* DEBUG: section 83 SSL accelerator support */
10
b3a8ae1b 11#include "squid.h"
d620ae0e 12#include "ssl/support.h"
b3a8ae1b
AR
13
14/* support.cc says this is needed */
31855516 15#if USE_OPENSSL
b3a8ae1b
AR
16
17#include "comm.h"
2e198b84 18#include "fd.h"
d620ae0e
CT
19#include "fde.h"
20#include "globals.h"
40f1e76d 21#include "ip/Address.h"
7c8ee688 22#include "parser/BinaryTokenizer.h"
edb876ab 23#include "SquidTime.h"
b3a8ae1b 24#include "ssl/bio.h"
8693472e 25
b3a8ae1b
AR
26#if HAVE_OPENSSL_SSL_H
27#include <openssl/ssl.h>
28#endif
29
b3a8ae1b
AR
30#if _SQUID_WINDOWS_
31extern int socket_read_method(int, char *, int);
32extern int socket_write_method(int, const char *, int);
33#endif
34
35/* BIO callbacks */
36static int squid_bio_write(BIO *h, const char *buf, int num);
37static int squid_bio_read(BIO *h, char *buf, int size);
38static int squid_bio_puts(BIO *h, const char *str);
39//static int squid_bio_gets(BIO *h, char *str, int size);
40static long squid_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
41static int squid_bio_create(BIO *h);
42static int squid_bio_destroy(BIO *data);
43/* SSL callbacks */
44static void squid_ssl_info(const SSL *ssl, int where, int ret);
45
093deea9 46#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
b3a8ae1b
AR
47/// Initialization structure for the BIO table with
48/// Squid-specific methods and BIO method wrappers.
49static BIO_METHOD SquidMethods = {
50 BIO_TYPE_SOCKET,
51 "squid",
52 squid_bio_write,
53 squid_bio_read,
54 squid_bio_puts,
55 NULL, // squid_bio_gets not supported
56 squid_bio_ctrl,
57 squid_bio_create,
58 squid_bio_destroy,
59 NULL // squid_callback_ctrl not supported
60};
093deea9
CT
61#else
62static BIO_METHOD *SquidMethods = NULL;
63#endif
b3a8ae1b
AR
64
65BIO *
86f77270 66Ssl::Bio::Create(const int fd, Security::Io::Type type)
b3a8ae1b 67{
093deea9 68#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
2a268a06 69 BIO_METHOD *useMethod = &SquidMethods;
093deea9
CT
70#else
71 if (!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);
80 }
2a268a06 81 const BIO_METHOD *useMethod = SquidMethods;
093deea9 82#endif
ac756c8c 83
2a268a06
CT
84 if (BIO *bio = BIO_new(useMethod)) {
85 BIO_int_ctrl(bio, BIO_C_SET_FD, type, fd);
86 return bio;
87 }
b3a8ae1b
AR
88 return NULL;
89}
90
91void
92Ssl::Bio::Link(SSL *ssl, BIO *bio)
93{
94 SSL_set_bio(ssl, bio, bio); // cannot fail
95 SSL_set_info_callback(ssl, &squid_ssl_info); // does not provide diagnostic
96}
97
b3a8ae1b
AR
98Ssl::Bio::Bio(const int anFd): fd_(anFd)
99{
100 debugs(83, 7, "Bio constructed, this=" << this << " FD " << fd_);
101}
102
103Ssl::Bio::~Bio()
104{
105 debugs(83, 7, "Bio destructing, this=" << this << " FD " << fd_);
b3a8ae1b
AR
106}
107
108int Ssl::Bio::write(const char *buf, int size, BIO *table)
109{
110 errno = 0;
111#if _SQUID_WINDOWS_
112 const int result = socket_write_method(fd_, buf, size);
113#else
114 const int result = default_write_method(fd_, buf, size);
115#endif
116 const int xerrno = errno;
117 debugs(83, 5, "FD " << fd_ << " wrote " << result << " <= " << size);
118
119 BIO_clear_retry_flags(table);
120 if (result < 0) {
121 const bool ignoreError = ignoreErrno(xerrno) != 0;
122 debugs(83, 5, "error: " << xerrno << " ignored: " << ignoreError);
123 if (ignoreError)
124 BIO_set_retry_write(table);
125 }
126
127 return result;
128}
129
130int
131Ssl::Bio::read(char *buf, int size, BIO *table)
132{
133 errno = 0;
134#if _SQUID_WINDOWS_
135 const int result = socket_read_method(fd_, buf, size);
136#else
137 const int result = default_read_method(fd_, buf, size);
138#endif
139 const int xerrno = errno;
140 debugs(83, 5, "FD " << fd_ << " read " << result << " <= " << size);
141
142 BIO_clear_retry_flags(table);
143 if (result < 0) {
144 const bool ignoreError = ignoreErrno(xerrno) != 0;
145 debugs(83, 5, "error: " << xerrno << " ignored: " << ignoreError);
146 if (ignoreError)
147 BIO_set_retry_read(table);
148 }
149
150 return result;
151}
152
153/// Called whenever the SSL connection state changes, an alert appears, or an
154/// error occurs. See SSL_set_info_callback().
155void
156Ssl::Bio::stateChanged(const SSL *ssl, int where, int ret)
157{
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.
161 // For example:
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");
166
d620ae0e 167 debugs(83, 7, "FD " << fd_ << " now: 0x" << std::hex << where << std::dec << ' ' <<
b3a8ae1b
AR
168 SSL_state_string(ssl) << " (" << SSL_state_string_long(ssl) << ")");
169}
170
edb876ab
CT
171Ssl::ClientBio::ClientBio(const int anFd):
172 Bio(anFd),
173 holdRead_(false),
174 holdWrite_(false),
175 helloSize(0),
176 abortReason(nullptr)
177{
178 renegotiations.configure(10*1000);
179}
180
e1f72a8b 181void
d620ae0e
CT
182Ssl::ClientBio::stateChanged(const SSL *ssl, int where, int ret)
183{
184 Ssl::Bio::stateChanged(ssl, where, ret);
edb876ab
CT
185 // detect client-initiated renegotiations DoS (CVE-2011-1473)
186 if (where & SSL_CB_HANDSHAKE_START) {
187 const int reneg = renegotiations.count(1);
188
189 if (abortReason)
190 return; // already decided and informed the admin
191
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).");
198 }
199 }
d620ae0e
CT
200}
201
202int
203Ssl::ClientBio::write(const char *buf, int size, BIO *table)
204{
edb876ab
CT
205 if (abortReason) {
206 debugs(83, 3, "BIO on FD " << fd_ << " is aborted");
207 BIO_clear_retry_flags(table);
208 return -1;
209 }
210
d620ae0e
CT
211 if (holdWrite_) {
212 BIO_set_retry_write(table);
213 return 0;
214 }
215
216 return Ssl::Bio::write(buf, size, table);
217}
218
d620ae0e
CT
219int
220Ssl::ClientBio::read(char *buf, int size, BIO *table)
221{
edb876ab
CT
222 if (abortReason) {
223 debugs(83, 3, "BIO on FD " << fd_ << " is aborted");
224 BIO_clear_retry_flags(table);
225 return -1;
226 }
227
d620ae0e
CT
228 if (holdRead_) {
229 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
230 BIO_set_retry_read(table);
231 return -1;
232 }
233
3cae14a6
CT
234 if (!rbuf.isEmpty()) {
235 int bytes = (size <= (int)rbuf.length() ? size : rbuf.length());
236 memcpy(buf, rbuf.rawContent(), bytes);
237 rbuf.consume(bytes);
238 return bytes;
239 } else
240 return Ssl::Bio::read(buf, size, table);
d620ae0e
CT
241
242 return -1;
243}
244
d20cf186
AR
245Ssl::ServerBio::ServerBio(const int anFd):
246 Bio(anFd),
247 helloMsgSize(0),
248 helloBuild(false),
249 allowSplice(false),
250 allowBump(false),
251 holdWrite_(false),
0bffe3ce 252 holdRead_(true),
d20cf186
AR
253 record_(false),
254 parsedHandshake(false),
0bffe3ce 255 parseError(false),
d20cf186
AR
256 bumpMode_(bumpNone),
257 rbufConsumePos(0)
258{
259}
260
d620ae0e
CT
261void
262Ssl::ServerBio::stateChanged(const SSL *ssl, int where, int ret)
263{
264 Ssl::Bio::stateChanged(ssl, where, ret);
265}
266
267void
21530947 268Ssl::ServerBio::setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &aHello)
d620ae0e 269{
21530947 270 clientTlsDetails = details;
6744c1a8 271 clientSentHello = aHello;
d620ae0e
CT
272};
273
55369ae6 274int
a465cd53 275Ssl::ServerBio::read(char *buf, int size, BIO *table)
55369ae6 276{
d20cf186 277 if (parsedHandshake) // done parsing TLS Hello
a465cd53 278 return readAndGive(buf, size, table);
d20cf186
AR
279 else
280 return readAndParse(buf, size, table);
a465cd53 281}
55369ae6 282
a465cd53
AR
283/// Read and give everything to OpenSSL.
284int
285Ssl::ServerBio::readAndGive(char *buf, const int size, BIO *table)
6821c276 286{
a465cd53
AR
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);
55369ae6 291
a465cd53
AR
292 if (record_) {
293 const int result = readAndBuffer(table);
294 if (result <= 0)
295 return result;
296 return giveBuffered(buf, size);
55369ae6
AR
297 }
298
a465cd53 299 return Ssl::Bio::read(buf, size, table);
55369ae6
AR
300}
301
a465cd53 302/// Read and give everything to our parser.
d20cf186 303/// When/if parsing is finished (successfully or not), start giving to OpenSSL.
d620ae0e 304int
a465cd53 305Ssl::ServerBio::readAndParse(char *buf, const int size, BIO *table)
d620ae0e 306{
a465cd53
AR
307 const int result = readAndBuffer(table);
308 if (result <= 0)
309 return result;
6821c276 310
d20cf186
AR
311 try {
312 if (!parser_.parseHello(rbuf)) {
313 // need more data to finish parsing
6821c276 314 BIO_set_retry_read(table);
a465cd53
AR
315 return -1;
316 }
d20cf186
AR
317 parsedHandshake = true; // done parsing (successfully)
318 }
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)
0bffe3ce 322 parseError = true;
55369ae6
AR
323 }
324
325 if (holdRead_) {
3945c91d
SM
326 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
327 BIO_set_retry_read(table);
328 return -1;
55369ae6
AR
329 }
330
a465cd53 331 return giveBuffered(buf, size);
6821c276 332}
55369ae6 333
a465cd53
AR
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.
d620ae0e 336int
a465cd53 337Ssl::ServerBio::readAndBuffer(BIO *table)
d620ae0e 338{
a465cd53
AR
339 char *space = rbuf.rawSpace(SQUID_TCP_SO_RCVBUF);
340 const int result = Ssl::Bio::read(space, rbuf.spaceSize(), table);
341 if (result <= 0)
342 return result;
6821c276 343
a465cd53
AR
344 rbuf.forceSize(rbuf.length() + result);
345 return result;
346}
6821c276 347
a465cd53
AR
348/// give previously buffered bytes to OpenSSL
349/// returns the number of bytes given
350int
351Ssl::ServerBio::giveBuffered(char *buf, const int size)
352{
353 if (rbuf.length() <= rbufConsumePos)
354 return -1; // buffered nothing yet
355
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");
361 return bytes;
d620ae0e
CT
362}
363
1110989a
CT
364// This function makes the required checks to examine if the client hello
365// message is compatible with the features provided by OpenSSL toolkit.
a95989ed 366// If the features are compatible and can be supported it tries to rewrite SSL
1110989a 367// structure members, to replace the hello message created by openSSL, with the
a95989ed 368// web client SSL hello message.
1110989a
CT
369// This is mostly possible in the cases where the web client uses openSSL
370// library similar with this one used by squid.
a95989ed 371static bool
21530947 372adjustSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, SBuf &helloMessage)
7f4e9b73 373{
a95989ed 374#if SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK
6744c1a8
CT
375 if (!details)
376 return false;
377
a95989ed
CT
378 if (!ssl->s3) {
379 debugs(83, 5, "No SSLv3 data found!");
380 return false;
381 }
382
7f4e9b73
CT
383 // If the client supports compression but our context does not support
384 // we can not adjust.
b4fca8e9 385#if !defined(OPENSSL_NO_COMP)
d9219c2b 386 const bool requireCompression = (details->compressionSupported && ssl->ctx->comp_methods == nullptr);
a36e9cb2 387#else
67c99fc6 388 const bool requireCompression = details->compressionSupported;
a36e9cb2
SH
389#endif
390 if (requireCompression) {
7f4e9b73 391 debugs(83, 5, "Client Hello Data supports compression, but we do not!");
a95989ed 392 return false;
7f4e9b73
CT
393 }
394
7f4e9b73 395#if !defined(SSL_TLSEXT_HB_ENABLED)
21530947 396 if (details->doHeartBeats) {
7f4e9b73 397 debugs(83, 5, "Client Hello Data supports HeartBeats but we do not support!");
a95989ed 398 return false;
7f4e9b73
CT
399 }
400#endif
401
c05c0c94
AR
402 if (details->unsupportedExtensions) {
403 debugs(83, 5, "Client Hello contains extensions that we do not support!");
404 return false;
405 }
406
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);
410 return false;
411 }
412
413 /* Check whether all on-the-wire ciphers are supported by OpenSSL. */
414
415 const auto &wireCiphers = details->ciphers;
416 Security::TlsDetails::Ciphers::size_type ciphersToFind = wireCiphers.size();
417
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.
8693472e 422#if defined(TLSEXT_TYPE_renegotiate)
c05c0c94
AR
423 // the 0x00FFFF mask converts 3-byte OpenSSL cipher to our 2-byte cipher
424 const uint16_t scsvCipher = SSL3_CK_SCSV & 0x00FFFF;
425#else
426 const uint16_t scsvCipher = 0;
7f4e9b73 427#endif
c05c0c94
AR
428
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))
435 --ciphersToFind;
7f4e9b73
CT
436 }
437
c05c0c94
AR
438 if (ciphersToFind > 0 && scsvCipher && wireCiphers.find(scsvCipher) != wireCiphers.end())
439 --ciphersToFind;
440
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!");
5d65362c 444 return false;
c05c0c94 445 }
7f4e9b73 446
a95989ed 447 debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
7f4e9b73
CT
448
449 //Adjust ssl structure data.
7f4e9b73 450 // We need to fix the random in SSL struct:
21530947
CT
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();
7f4e9b73 455
21530947
CT
456 size_t mainHelloSize = helloMessage.length() - 5;
457 const char *mainHello = helloMessage.rawContent() + 5;
4cabb5e5 458 assert((size_t)ssl->init_buf->max > mainHelloSize);
7f4e9b73
CT
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;
a95989ed
CT
464 return true;
465#else
466 return false;
467#endif
7f4e9b73
CT
468}
469
d620ae0e
CT
470int
471Ssl::ServerBio::write(const char *buf, int size, BIO *table)
472{
473
474 if (holdWrite_) {
a465cd53 475 debugs(83, 7, "postpone writing " << size << " bytes to SSL FD " << fd_);
d620ae0e
CT
476 BIO_set_retry_write(table);
477 return -1;
478 }
479
5d65362c 480 if (!helloBuild && (bumpMode_ == Ssl::bumpPeek || bumpMode_ == Ssl::bumpStare)) {
6744c1a8
CT
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+
488
489 //Hello message is the first message we write to server
490 assert(helloMsg.isEmpty());
491
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))
5d65362c 497 allowBump = true;
6744c1a8
CT
498 allowSplice = true;
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*/
503 allowBump = true;
504 if (!clientSentHello.isEmpty() && adjustSSL(ssl, clientTlsDetails, clientSentHello)) {
505 allowSplice = true;
506 helloMsg.append(clientSentHello);
507 debugs(83, 7, "FD " << fd_ << ": Using client-sent ClientHello for stare mode");
7f4e9b73 508 }
d620ae0e
CT
509 }
510 }
6744c1a8 511 // if we did not use the client-sent ClientHello, then use the OpenSSL-generated one
8693472e 512 if (helloMsg.isEmpty())
7f4e9b73
CT
513 helloMsg.append(buf, size);
514
d620ae0e 515 helloBuild = true;
8693472e 516 helloMsgSize = helloMsg.length();
5d65362c 517 //allowBump = true;
7f4e9b73
CT
518
519 if (allowSplice) {
e1f72a8b 520 // Do not write yet.....
7f4e9b73
CT
521 BIO_set_retry_write(table);
522 return -1;
523 }
d620ae0e
CT
524 }
525
8693472e 526 if (!helloMsg.isEmpty()) {
d620ae0e 527 debugs(83, 7, "buffered write for FD " << fd_);
8693472e 528 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
d620ae0e 529 helloMsg.consume(ret);
8693472e 530 if (!helloMsg.isEmpty()) {
d620ae0e
CT
531 // We need to retry sendind data.
532 // Say to openSSL to retry sending hello message
533 BIO_set_retry_write(table);
534 return -1;
535 }
536
537 // Sending hello message complete. Do not send more data for now...
7f4e9b73
CT
538 holdWrite_ = true;
539
a95989ed
CT
540 // spoof openSSL that we write what it ask us to write
541 return size;
d620ae0e
CT
542 } else
543 return Ssl::Bio::write(buf, size, table);
544}
545
546void
547Ssl::ServerBio::flush(BIO *table)
548{
8693472e
CT
549 if (!helloMsg.isEmpty()) {
550 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
d620ae0e
CT
551 helloMsg.consume(ret);
552 }
553}
554
89c5ca0f
CT
555bool
556Ssl::ServerBio::resumingSession()
557{
d9219c2b 558 return parser_.resumingSession;
55369ae6 559}
89c5ca0f 560
b3a8ae1b
AR
561/// initializes BIO table after allocation
562static int
563squid_bio_create(BIO *bi)
564{
093deea9 565#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
b3a8ae1b
AR
566 bi->init = 0; // set when we store Bio object and socket fd (BIO_C_SET_FD)
567 bi->num = 0;
b3a8ae1b 568 bi->flags = 0;
093deea9
CT
569#else
570 // No need to set more, openSSL initialize BIO memory to zero.
571#endif
572
573 BIO_set_data(bi, NULL);
b3a8ae1b
AR
574 return 1;
575}
576
577/// cleans BIO table before deallocation
578static int
579squid_bio_destroy(BIO *table)
580{
093deea9
CT
581 delete static_cast<Ssl::Bio*>(BIO_get_data(table));
582 BIO_set_data(table, NULL);
b3a8ae1b
AR
583 return 1;
584}
585
586/// wrapper for Bio::write()
587static int
588squid_bio_write(BIO *table, const char *buf, int size)
589{
093deea9 590 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
b3a8ae1b
AR
591 assert(bio);
592 return bio->write(buf, size, table);
593}
594
595/// wrapper for Bio::read()
596static int
597squid_bio_read(BIO *table, char *buf, int size)
598{
093deea9 599 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
b3a8ae1b
AR
600 assert(bio);
601 return bio->read(buf, size, table);
602}
603
604/// implements puts() via write()
605static int
606squid_bio_puts(BIO *table, const char *str)
607{
608 assert(str);
609 return squid_bio_write(table, str, strlen(str));
610}
611
612/// other BIO manipulations (those without dedicated callbacks in BIO table)
613static long
614squid_bio_ctrl(BIO *table, int cmd, long arg1, void *arg2)
615{
616 debugs(83, 5, table << ' ' << cmd << '(' << arg1 << ", " << arg2 << ')');
617
618 switch (cmd) {
619 case BIO_C_SET_FD: {
620 assert(arg2);
621 const int fd = *static_cast<int*>(arg2);
d620ae0e 622 Ssl::Bio *bio;
86f77270 623 if (arg1 == Security::Io::BIO_TO_SERVER)
d620ae0e
CT
624 bio = new Ssl::ServerBio(fd);
625 else
626 bio = new Ssl::ClientBio(fd);
093deea9
CT
627 assert(!BIO_get_data(table));
628 BIO_set_data(table, bio);
629 BIO_set_init(table, 1);
b3a8ae1b
AR
630 return 0;
631 }
632
633 case BIO_C_GET_FD:
093deea9
CT
634 if (BIO_get_init(table)) {
635 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
b3a8ae1b
AR
636 assert(bio);
637 if (arg2)
638 *static_cast<int*>(arg2) = bio->fd();
639 return bio->fd();
640 }
641 return -1;
642
54f3b032 643 case BIO_CTRL_DUP:
e1f72a8b 644 // Should implemented if the SSL_dup openSSL API function
54f3b032
CT
645 // used anywhere in squid.
646 return 0;
647
b3a8ae1b 648 case BIO_CTRL_FLUSH:
093deea9
CT
649 if (BIO_get_init(table)) {
650 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
b3a8ae1b 651 assert(bio);
d620ae0e 652 bio->flush(table);
b3a8ae1b
AR
653 return 1;
654 }
655 return 0;
656
f53969cc
SM
657 /* we may also need to implement these:
658 case BIO_CTRL_RESET:
659 case BIO_C_FILE_SEEK:
660 case BIO_C_FILE_TELL:
661 case BIO_CTRL_INFO:
662 case BIO_CTRL_GET_CLOSE:
663 case BIO_CTRL_SET_CLOSE:
664 case BIO_CTRL_PENDING:
665 case BIO_CTRL_WPENDING:
666 */
b3a8ae1b
AR
667 default:
668 return 0;
669
670 }
671
672 return 0; /* NOTREACHED */
673}
674
675/// wrapper for Bio::stateChanged()
676static void
677squid_ssl_info(const SSL *ssl, int where, int ret)
678{
679 if (BIO *table = SSL_get_rbio(ssl)) {
093deea9 680 if (Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table)))
b3a8ae1b
AR
681 bio->stateChanged(ssl, where, ret);
682 }
683}
684
21530947
CT
685void
686applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode)
d620ae0e 687{
21530947
CT
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.
d9219c2b
CT
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.
21530947
CT
694 // For example will prevent comunnicating with a tls1.0 server if the
695 // client sent and tlsv1.2 Hello message.
e1f72a8b 696#if defined(TLSEXT_NAMETYPE_host_name)
21530947
CT
697 if (!details->serverName.isEmpty()) {
698 SSL_set_tlsext_host_name(ssl, details->serverName.c_str());
458fd470 699 }
e68e8b9a 700#endif
2bcab852 701
21530947
CT
702 if (!details->ciphers.empty()) {
703 SBuf strCiphers;
704 for (auto cipherId: details->ciphers) {
705 unsigned char cbytes[3];
706 cbytes[0] = (cipherId >> 8) & 0xFF;
707 cbytes[1] = cipherId & 0xFF;
708 cbytes[2] = 0;
093deea9 709#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
21530947 710 const SSL_METHOD *method = SSLv23_method();
21530947 711 const SSL_CIPHER *c = method->get_cipher_by_char(cbytes);
093deea9
CT
712#else
713 const SSL_CIPHER *c = SSL_CIPHER_find(ssl, cbytes);
714#endif
d620ae0e 715 if (c != NULL) {
21530947
CT
716 if (!strCiphers.isEmpty())
717 strCiphers.append(":");
093deea9 718 strCiphers.append(SSL_CIPHER_get_name(c));
d620ae0e
CT
719 }
720 }
21530947
CT
721 if (!strCiphers.isEmpty())
722 SSL_set_cipher_list(ssl, strCiphers.c_str());
d620ae0e 723 }
d620ae0e 724
8693472e 725#if defined(SSL_OP_NO_COMPRESSION) /* XXX: OpenSSL 0.9.8k lacks SSL_OP_NO_COMPRESSION */
67c99fc6 726 if (!details->compressionSupported)
a95989ed
CT
727 SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
728#endif
729
89c5ca0f 730#if defined(TLSEXT_STATUSTYPE_ocsp)
21530947 731 if (details->tlsStatusRequest)
89c5ca0f
CT
732 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
733#endif
734
735#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
21530947 736 if (!details->tlsAppLayerProtoNeg.isEmpty()) {
89c5ca0f 737 if (bumpMode == Ssl::bumpPeek)
3152460d 738 SSL_set_alpn_protos(ssl, (const unsigned char*)details->tlsAppLayerProtoNeg.rawContent(), details->tlsAppLayerProtoNeg.length());
89c5ca0f
CT
739 else {
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));
742 }
743 }
744#endif
a95989ed
CT
745}
746
21530947 747#endif // USE_OPENSSL
f53969cc 748