]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/bio.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / ssl / bio.cc
CommitLineData
b3a8ae1b 1/*
ef57eb7b 2 * Copyright (C) 1996-2016 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"
b3a8ae1b 23#include "ssl/bio.h"
8693472e 24
b3a8ae1b
AR
25#if HAVE_OPENSSL_SSL_H
26#include <openssl/ssl.h>
27#endif
28
b3a8ae1b
AR
29#if _SQUID_WINDOWS_
30extern int socket_read_method(int, char *, int);
31extern int socket_write_method(int, const char *, int);
32#endif
33
34/* BIO callbacks */
35static int squid_bio_write(BIO *h, const char *buf, int num);
36static int squid_bio_read(BIO *h, char *buf, int size);
37static int squid_bio_puts(BIO *h, const char *str);
38//static int squid_bio_gets(BIO *h, char *str, int size);
39static long squid_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
40static int squid_bio_create(BIO *h);
41static int squid_bio_destroy(BIO *data);
42/* SSL callbacks */
43static void squid_ssl_info(const SSL *ssl, int where, int ret);
44
45/// Initialization structure for the BIO table with
46/// Squid-specific methods and BIO method wrappers.
47static BIO_METHOD SquidMethods = {
48 BIO_TYPE_SOCKET,
49 "squid",
50 squid_bio_write,
51 squid_bio_read,
52 squid_bio_puts,
53 NULL, // squid_bio_gets not supported
54 squid_bio_ctrl,
55 squid_bio_create,
56 squid_bio_destroy,
57 NULL // squid_callback_ctrl not supported
58};
59
60BIO *
d620ae0e 61Ssl::Bio::Create(const int fd, Ssl::Bio::Type type)
b3a8ae1b
AR
62{
63 if (BIO *bio = BIO_new(&SquidMethods)) {
d620ae0e 64 BIO_int_ctrl(bio, BIO_C_SET_FD, type, fd);
b3a8ae1b
AR
65 return bio;
66 }
67 return NULL;
68}
69
70void
71Ssl::Bio::Link(SSL *ssl, BIO *bio)
72{
73 SSL_set_bio(ssl, bio, bio); // cannot fail
74 SSL_set_info_callback(ssl, &squid_ssl_info); // does not provide diagnostic
75}
76
b3a8ae1b
AR
77Ssl::Bio::Bio(const int anFd): fd_(anFd)
78{
79 debugs(83, 7, "Bio constructed, this=" << this << " FD " << fd_);
80}
81
82Ssl::Bio::~Bio()
83{
84 debugs(83, 7, "Bio destructing, this=" << this << " FD " << fd_);
b3a8ae1b
AR
85}
86
87int Ssl::Bio::write(const char *buf, int size, BIO *table)
88{
89 errno = 0;
90#if _SQUID_WINDOWS_
91 const int result = socket_write_method(fd_, buf, size);
92#else
93 const int result = default_write_method(fd_, buf, size);
94#endif
95 const int xerrno = errno;
96 debugs(83, 5, "FD " << fd_ << " wrote " << result << " <= " << size);
97
98 BIO_clear_retry_flags(table);
99 if (result < 0) {
100 const bool ignoreError = ignoreErrno(xerrno) != 0;
101 debugs(83, 5, "error: " << xerrno << " ignored: " << ignoreError);
102 if (ignoreError)
103 BIO_set_retry_write(table);
104 }
105
106 return result;
107}
108
109int
110Ssl::Bio::read(char *buf, int size, BIO *table)
111{
112 errno = 0;
113#if _SQUID_WINDOWS_
114 const int result = socket_read_method(fd_, buf, size);
115#else
116 const int result = default_read_method(fd_, buf, size);
117#endif
118 const int xerrno = errno;
119 debugs(83, 5, "FD " << fd_ << " read " << result << " <= " << size);
120
121 BIO_clear_retry_flags(table);
122 if (result < 0) {
123 const bool ignoreError = ignoreErrno(xerrno) != 0;
124 debugs(83, 5, "error: " << xerrno << " ignored: " << ignoreError);
125 if (ignoreError)
126 BIO_set_retry_read(table);
127 }
128
129 return result;
130}
131
132/// Called whenever the SSL connection state changes, an alert appears, or an
133/// error occurs. See SSL_set_info_callback().
134void
135Ssl::Bio::stateChanged(const SSL *ssl, int where, int ret)
136{
137 // Here we can use (where & STATE) to check the current state.
138 // Many STATE values are possible, including: SSL_CB_CONNECT_LOOP,
139 // SSL_CB_ACCEPT_LOOP, SSL_CB_HANDSHAKE_START, and SSL_CB_HANDSHAKE_DONE.
140 // For example:
141 // if (where & SSL_CB_HANDSHAKE_START)
142 // debugs(83, 9, "Trying to establish the SSL connection");
143 // else if (where & SSL_CB_HANDSHAKE_DONE)
144 // debugs(83, 9, "SSL connection established");
145
d620ae0e 146 debugs(83, 7, "FD " << fd_ << " now: 0x" << std::hex << where << std::dec << ' ' <<
b3a8ae1b
AR
147 SSL_state_string(ssl) << " (" << SSL_state_string_long(ssl) << ")");
148}
149
d620ae0e
CT
150bool
151Ssl::ClientBio::isClientHello(int state)
152{
d85aad1b 153 return (
c05a5e2d
SM
154 state == SSL3_ST_SR_CLNT_HELLO_A ||
155 state == SSL23_ST_SR_CLNT_HELLO_A ||
156 state == SSL23_ST_SR_CLNT_HELLO_B ||
157 state == SSL3_ST_SR_CLNT_HELLO_B ||
158 state == SSL3_ST_SR_CLNT_HELLO_C
e1f72a8b 159 );
d620ae0e
CT
160}
161
e1f72a8b 162void
d620ae0e
CT
163Ssl::ClientBio::stateChanged(const SSL *ssl, int where, int ret)
164{
165 Ssl::Bio::stateChanged(ssl, where, ret);
166}
167
168int
169Ssl::ClientBio::write(const char *buf, int size, BIO *table)
170{
171 if (holdWrite_) {
172 BIO_set_retry_write(table);
173 return 0;
174 }
175
176 return Ssl::Bio::write(buf, size, table);
177}
178
d620ae0e
CT
179int
180Ssl::ClientBio::read(char *buf, int size, BIO *table)
181{
d620ae0e
CT
182 if (holdRead_) {
183 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
184 BIO_set_retry_read(table);
185 return -1;
186 }
187
3cae14a6
CT
188 if (!rbuf.isEmpty()) {
189 int bytes = (size <= (int)rbuf.length() ? size : rbuf.length());
190 memcpy(buf, rbuf.rawContent(), bytes);
191 rbuf.consume(bytes);
192 return bytes;
193 } else
194 return Ssl::Bio::read(buf, size, table);
d620ae0e
CT
195
196 return -1;
197}
198
d20cf186
AR
199Ssl::ServerBio::ServerBio(const int anFd):
200 Bio(anFd),
201 helloMsgSize(0),
202 helloBuild(false),
203 allowSplice(false),
204 allowBump(false),
205 holdWrite_(false),
0bffe3ce 206 holdRead_(true),
d20cf186
AR
207 record_(false),
208 parsedHandshake(false),
0bffe3ce 209 parseError(false),
d20cf186
AR
210 bumpMode_(bumpNone),
211 rbufConsumePos(0)
212{
213}
214
d620ae0e
CT
215void
216Ssl::ServerBio::stateChanged(const SSL *ssl, int where, int ret)
217{
218 Ssl::Bio::stateChanged(ssl, where, ret);
219}
220
221void
21530947 222Ssl::ServerBio::setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &aHello)
d620ae0e 223{
21530947
CT
224 clientTlsDetails = details;
225 clientHelloMessage = aHello;
d620ae0e
CT
226};
227
55369ae6 228int
a465cd53 229Ssl::ServerBio::read(char *buf, int size, BIO *table)
55369ae6 230{
d20cf186 231 if (parsedHandshake) // done parsing TLS Hello
a465cd53 232 return readAndGive(buf, size, table);
d20cf186
AR
233 else
234 return readAndParse(buf, size, table);
a465cd53 235}
55369ae6 236
a465cd53
AR
237/// Read and give everything to OpenSSL.
238int
239Ssl::ServerBio::readAndGive(char *buf, const int size, BIO *table)
6821c276 240{
a465cd53
AR
241 // If we have unused buffered bytes, give those bytes to OpenSSL now,
242 // before reading more. TODO: Read if we have buffered less than size?
243 if (rbufConsumePos < rbuf.length())
244 return giveBuffered(buf, size);
55369ae6 245
a465cd53
AR
246 if (record_) {
247 const int result = readAndBuffer(table);
248 if (result <= 0)
249 return result;
250 return giveBuffered(buf, size);
55369ae6
AR
251 }
252
a465cd53 253 return Ssl::Bio::read(buf, size, table);
55369ae6
AR
254}
255
a465cd53 256/// Read and give everything to our parser.
d20cf186 257/// When/if parsing is finished (successfully or not), start giving to OpenSSL.
d620ae0e 258int
a465cd53 259Ssl::ServerBio::readAndParse(char *buf, const int size, BIO *table)
d620ae0e 260{
a465cd53
AR
261 const int result = readAndBuffer(table);
262 if (result <= 0)
263 return result;
6821c276 264
d20cf186
AR
265 try {
266 if (!parser_.parseHello(rbuf)) {
267 // need more data to finish parsing
6821c276 268 BIO_set_retry_read(table);
a465cd53
AR
269 return -1;
270 }
d20cf186
AR
271 parsedHandshake = true; // done parsing (successfully)
272 }
273 catch (const std::exception &ex) {
274 debugs(83, 2, "parsing error on FD " << fd_ << ": " << ex.what());
275 parsedHandshake = true; // done parsing (due to an error)
0bffe3ce 276 parseError = true;
55369ae6
AR
277 }
278
279 if (holdRead_) {
3945c91d
SM
280 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
281 BIO_set_retry_read(table);
282 return -1;
55369ae6
AR
283 }
284
a465cd53 285 return giveBuffered(buf, size);
6821c276 286}
55369ae6 287
a465cd53
AR
288/// Reads more data into the read buffer. Returns either the number of bytes
289/// read or, on errors (including "try again" errors), a negative number.
d620ae0e 290int
a465cd53 291Ssl::ServerBio::readAndBuffer(BIO *table)
d620ae0e 292{
a465cd53
AR
293 char *space = rbuf.rawSpace(SQUID_TCP_SO_RCVBUF);
294 const int result = Ssl::Bio::read(space, rbuf.spaceSize(), table);
295 if (result <= 0)
296 return result;
6821c276 297
a465cd53
AR
298 rbuf.forceSize(rbuf.length() + result);
299 return result;
300}
6821c276 301
a465cd53
AR
302/// give previously buffered bytes to OpenSSL
303/// returns the number of bytes given
304int
305Ssl::ServerBio::giveBuffered(char *buf, const int size)
306{
307 if (rbuf.length() <= rbufConsumePos)
308 return -1; // buffered nothing yet
309
310 const int unsent = rbuf.length() - rbufConsumePos;
311 const int bytes = (size <= unsent ? size : unsent);
312 memcpy(buf, rbuf.rawContent() + rbufConsumePos, bytes);
313 rbufConsumePos += bytes;
314 debugs(83, 7, bytes << "<=" << size << " bytes to OpenSSL");
315 return bytes;
d620ae0e
CT
316}
317
1110989a
CT
318// This function makes the required checks to examine if the client hello
319// message is compatible with the features provided by OpenSSL toolkit.
a95989ed 320// If the features are compatible and can be supported it tries to rewrite SSL
1110989a 321// structure members, to replace the hello message created by openSSL, with the
a95989ed 322// web client SSL hello message.
1110989a
CT
323// This is mostly possible in the cases where the web client uses openSSL
324// library similar with this one used by squid.
a95989ed 325static bool
21530947 326adjustSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, SBuf &helloMessage)
7f4e9b73 327{
a95989ed
CT
328#if SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK
329 if (!ssl->s3) {
330 debugs(83, 5, "No SSLv3 data found!");
331 return false;
332 }
333
7f4e9b73
CT
334 // If the client supports compression but our context does not support
335 // we can not adjust.
b4fca8e9 336#if !defined(OPENSSL_NO_COMP)
d9219c2b 337 const bool requireCompression = (details->compressionSupported && ssl->ctx->comp_methods == nullptr);
a36e9cb2 338#else
67c99fc6 339 const bool requireCompression = details->compressionSupported;
a36e9cb2
SH
340#endif
341 if (requireCompression) {
7f4e9b73 342 debugs(83, 5, "Client Hello Data supports compression, but we do not!");
a95989ed 343 return false;
7f4e9b73
CT
344 }
345
7f4e9b73 346#if !defined(SSL_TLSEXT_HB_ENABLED)
21530947 347 if (details->doHeartBeats) {
7f4e9b73 348 debugs(83, 5, "Client Hello Data supports HeartBeats but we do not support!");
a95989ed 349 return false;
7f4e9b73
CT
350 }
351#endif
352
c05c0c94
AR
353 if (details->unsupportedExtensions) {
354 debugs(83, 5, "Client Hello contains extensions that we do not support!");
355 return false;
356 }
357
358 SSL3_BUFFER *wb=&(ssl->s3->wbuf);
359 if (wb->len < (size_t)helloMessage.length()) {
360 debugs(83, 5, "Client Hello exceeds OpenSSL buffer: " << helloMessage.length() << " >= " << wb->len);
361 return false;
362 }
363
364 /* Check whether all on-the-wire ciphers are supported by OpenSSL. */
365
366 const auto &wireCiphers = details->ciphers;
367 Security::TlsDetails::Ciphers::size_type ciphersToFind = wireCiphers.size();
368
369 // RFC 5746: "TLS_EMPTY_RENEGOTIATION_INFO_SCSV is not a true cipher suite".
370 // It is commonly seen on the wire, including in from-OpenSSL traffic, but
371 // SSL_get_ciphers() does not return this _pseudo_ cipher suite in my tests.
372 // If OpenSSL supports scsvCipher, we count it (at most once) further below.
8693472e 373#if defined(TLSEXT_TYPE_renegotiate)
c05c0c94
AR
374 // the 0x00FFFF mask converts 3-byte OpenSSL cipher to our 2-byte cipher
375 const uint16_t scsvCipher = SSL3_CK_SCSV & 0x00FFFF;
376#else
377 const uint16_t scsvCipher = 0;
7f4e9b73 378#endif
c05c0c94
AR
379
380 STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(ssl);
381 const int supportedCipherCount = sk_SSL_CIPHER_num(cipher_stack);
382 for (int idx = 0; idx < supportedCipherCount && ciphersToFind > 0; ++idx) {
383 const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(cipher_stack, idx);
384 const auto id = SSL_CIPHER_get_id(cipher) & 0x00FFFF;
385 if (wireCiphers.find(id) != wireCiphers.end() && (!scsvCipher || id != scsvCipher))
386 --ciphersToFind;
7f4e9b73
CT
387 }
388
c05c0c94
AR
389 if (ciphersToFind > 0 && scsvCipher && wireCiphers.find(scsvCipher) != wireCiphers.end())
390 --ciphersToFind;
391
392 if (ciphersToFind > 0) {
393 // TODO: Add slowlyReportUnsupportedCiphers() to slowly find and report each of them
394 debugs(83, 5, "Client Hello Data has " << ciphersToFind << " ciphers that we do not support!");
5d65362c 395 return false;
c05c0c94 396 }
7f4e9b73 397
a95989ed 398 debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
7f4e9b73
CT
399
400 //Adjust ssl structure data.
7f4e9b73 401 // We need to fix the random in SSL struct:
21530947
CT
402 if (details->clientRandom.length() == SSL3_RANDOM_SIZE)
403 memcpy(ssl->s3->client_random, details->clientRandom.c_str(), SSL3_RANDOM_SIZE);
404 memcpy(wb->buf, helloMessage.rawContent(), helloMessage.length());
405 wb->left = helloMessage.length();
7f4e9b73 406
21530947
CT
407 size_t mainHelloSize = helloMessage.length() - 5;
408 const char *mainHello = helloMessage.rawContent() + 5;
4cabb5e5 409 assert((size_t)ssl->init_buf->max > mainHelloSize);
7f4e9b73
CT
410 memcpy(ssl->init_buf->data, mainHello, mainHelloSize);
411 debugs(83, 5, "Hello Data init and adjustd sizes :" << ssl->init_num << " = "<< mainHelloSize);
412 ssl->init_num = mainHelloSize;
413 ssl->s3->wpend_ret = mainHelloSize;
414 ssl->s3->wpend_tot = mainHelloSize;
a95989ed
CT
415 return true;
416#else
417 return false;
418#endif
7f4e9b73
CT
419}
420
d620ae0e
CT
421int
422Ssl::ServerBio::write(const char *buf, int size, BIO *table)
423{
424
425 if (holdWrite_) {
a465cd53 426 debugs(83, 7, "postpone writing " << size << " bytes to SSL FD " << fd_);
d620ae0e
CT
427 BIO_set_retry_write(table);
428 return -1;
429 }
430
5d65362c 431 if (!helloBuild && (bumpMode_ == Ssl::bumpPeek || bumpMode_ == Ssl::bumpStare)) {
d620ae0e
CT
432 if (
433 buf[1] >= 3 //it is an SSL Version3 message
434 && buf[0] == 0x16 // and it is a Handshake/Hello message
e1f72a8b 435 ) {
d620ae0e
CT
436
437 //Hello message is the first message we write to server
8693472e 438 assert(helloMsg.isEmpty());
d620ae0e 439
33cc0629 440 auto ssl = fd_table[fd_].ssl.get();
21530947 441 if (ssl) {
5d65362c 442 if (bumpMode_ == Ssl::bumpPeek) {
21530947 443 if (adjustSSL(ssl, clientTlsDetails, clientHelloMessage))
5d65362c 444 allowBump = true;
7f4e9b73 445 allowSplice = true;
21530947 446 helloMsg.append(clientHelloMessage);
35178e02 447 debugs(83, 7, "SSL HELLO message for FD " << fd_ << ": Random number is adjusted for peek mode");
5d65362c
CT
448 } else { /*Ssl::bumpStare*/
449 allowBump = true;
21530947 450 if (adjustSSL(ssl, clientTlsDetails, clientHelloMessage)) {
5d65362c 451 allowSplice = true;
21530947 452 helloMsg.append(clientHelloMessage);
35178e02
CT
453 debugs(83, 7, "SSL HELLO message for FD " << fd_ << ": Random number is adjusted for stare mode");
454 }
7f4e9b73 455 }
d620ae0e
CT
456 }
457 }
7f4e9b73 458 // If we do not build any hello message, copy the current
8693472e 459 if (helloMsg.isEmpty())
7f4e9b73
CT
460 helloMsg.append(buf, size);
461
d620ae0e 462 helloBuild = true;
8693472e 463 helloMsgSize = helloMsg.length();
5d65362c 464 //allowBump = true;
7f4e9b73
CT
465
466 if (allowSplice) {
e1f72a8b 467 // Do not write yet.....
7f4e9b73
CT
468 BIO_set_retry_write(table);
469 return -1;
470 }
d620ae0e
CT
471 }
472
8693472e 473 if (!helloMsg.isEmpty()) {
d620ae0e 474 debugs(83, 7, "buffered write for FD " << fd_);
8693472e 475 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
d620ae0e 476 helloMsg.consume(ret);
8693472e 477 if (!helloMsg.isEmpty()) {
d620ae0e
CT
478 // We need to retry sendind data.
479 // Say to openSSL to retry sending hello message
480 BIO_set_retry_write(table);
481 return -1;
482 }
483
484 // Sending hello message complete. Do not send more data for now...
7f4e9b73
CT
485 holdWrite_ = true;
486
a95989ed
CT
487 // spoof openSSL that we write what it ask us to write
488 return size;
d620ae0e
CT
489 } else
490 return Ssl::Bio::write(buf, size, table);
491}
492
493void
494Ssl::ServerBio::flush(BIO *table)
495{
8693472e
CT
496 if (!helloMsg.isEmpty()) {
497 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
d620ae0e
CT
498 helloMsg.consume(ret);
499 }
500}
501
89c5ca0f
CT
502bool
503Ssl::ServerBio::resumingSession()
504{
d9219c2b 505 return parser_.resumingSession;
55369ae6 506}
89c5ca0f 507
b3a8ae1b
AR
508/// initializes BIO table after allocation
509static int
510squid_bio_create(BIO *bi)
511{
512 bi->init = 0; // set when we store Bio object and socket fd (BIO_C_SET_FD)
513 bi->num = 0;
514 bi->ptr = NULL;
515 bi->flags = 0;
516 return 1;
517}
518
519/// cleans BIO table before deallocation
520static int
521squid_bio_destroy(BIO *table)
522{
523 delete static_cast<Ssl::Bio*>(table->ptr);
524 table->ptr = NULL;
525 return 1;
526}
527
528/// wrapper for Bio::write()
529static int
530squid_bio_write(BIO *table, const char *buf, int size)
531{
532 Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr);
533 assert(bio);
534 return bio->write(buf, size, table);
535}
536
537/// wrapper for Bio::read()
538static int
539squid_bio_read(BIO *table, char *buf, int size)
540{
541 Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr);
542 assert(bio);
543 return bio->read(buf, size, table);
544}
545
546/// implements puts() via write()
547static int
548squid_bio_puts(BIO *table, const char *str)
549{
550 assert(str);
551 return squid_bio_write(table, str, strlen(str));
552}
553
554/// other BIO manipulations (those without dedicated callbacks in BIO table)
555static long
556squid_bio_ctrl(BIO *table, int cmd, long arg1, void *arg2)
557{
558 debugs(83, 5, table << ' ' << cmd << '(' << arg1 << ", " << arg2 << ')');
559
560 switch (cmd) {
561 case BIO_C_SET_FD: {
562 assert(arg2);
563 const int fd = *static_cast<int*>(arg2);
d620ae0e
CT
564 Ssl::Bio *bio;
565 if (arg1 == Ssl::Bio::BIO_TO_SERVER)
566 bio = new Ssl::ServerBio(fd);
567 else
568 bio = new Ssl::ClientBio(fd);
b3a8ae1b
AR
569 assert(!table->ptr);
570 table->ptr = bio;
571 table->init = 1;
572 return 0;
573 }
574
575 case BIO_C_GET_FD:
576 if (table->init) {
577 Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr);
578 assert(bio);
579 if (arg2)
580 *static_cast<int*>(arg2) = bio->fd();
581 return bio->fd();
582 }
583 return -1;
584
54f3b032 585 case BIO_CTRL_DUP:
e1f72a8b 586 // Should implemented if the SSL_dup openSSL API function
54f3b032
CT
587 // used anywhere in squid.
588 return 0;
589
b3a8ae1b
AR
590 case BIO_CTRL_FLUSH:
591 if (table->init) {
592 Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr);
593 assert(bio);
d620ae0e 594 bio->flush(table);
b3a8ae1b
AR
595 return 1;
596 }
597 return 0;
598
f53969cc
SM
599 /* we may also need to implement these:
600 case BIO_CTRL_RESET:
601 case BIO_C_FILE_SEEK:
602 case BIO_C_FILE_TELL:
603 case BIO_CTRL_INFO:
604 case BIO_CTRL_GET_CLOSE:
605 case BIO_CTRL_SET_CLOSE:
606 case BIO_CTRL_PENDING:
607 case BIO_CTRL_WPENDING:
608 */
b3a8ae1b
AR
609 default:
610 return 0;
611
612 }
613
614 return 0; /* NOTREACHED */
615}
616
617/// wrapper for Bio::stateChanged()
618static void
619squid_ssl_info(const SSL *ssl, int where, int ret)
620{
621 if (BIO *table = SSL_get_rbio(ssl)) {
622 if (Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr))
623 bio->stateChanged(ssl, where, ret);
624 }
625}
626
21530947
CT
627void
628applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode)
d620ae0e 629{
21530947
CT
630 // To increase the possibility for bumping after peek mode selection or
631 // splicing after stare mode selection it is good to set the
632 // SSL protocol version.
d9219c2b
CT
633 // The SSL_set_ssl_method is wrong here because it will restrict the
634 // permitted transport version to be identical to the version used in the
635 // ClientHello message.
21530947
CT
636 // For example will prevent comunnicating with a tls1.0 server if the
637 // client sent and tlsv1.2 Hello message.
e1f72a8b 638#if defined(TLSEXT_NAMETYPE_host_name)
21530947
CT
639 if (!details->serverName.isEmpty()) {
640 SSL_set_tlsext_host_name(ssl, details->serverName.c_str());
458fd470 641 }
e68e8b9a 642#endif
2bcab852 643
21530947
CT
644 if (!details->ciphers.empty()) {
645 SBuf strCiphers;
646 for (auto cipherId: details->ciphers) {
647 unsigned char cbytes[3];
648 cbytes[0] = (cipherId >> 8) & 0xFF;
649 cbytes[1] = cipherId & 0xFF;
650 cbytes[2] = 0;
e68e8b9a 651#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
21530947 652 const SSL_METHOD *method = TLS_method();
e68e8b9a 653#else
21530947 654 const SSL_METHOD *method = SSLv23_method();
e68e8b9a 655#endif
21530947 656 const SSL_CIPHER *c = method->get_cipher_by_char(cbytes);
d620ae0e 657 if (c != NULL) {
21530947
CT
658 if (!strCiphers.isEmpty())
659 strCiphers.append(":");
660 strCiphers.append(c->name);
d620ae0e
CT
661 }
662 }
21530947
CT
663 if (!strCiphers.isEmpty())
664 SSL_set_cipher_list(ssl, strCiphers.c_str());
d620ae0e 665 }
d620ae0e 666
8693472e 667#if defined(SSL_OP_NO_COMPRESSION) /* XXX: OpenSSL 0.9.8k lacks SSL_OP_NO_COMPRESSION */
67c99fc6 668 if (!details->compressionSupported)
a95989ed
CT
669 SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
670#endif
671
89c5ca0f 672#if defined(TLSEXT_STATUSTYPE_ocsp)
21530947 673 if (details->tlsStatusRequest)
89c5ca0f
CT
674 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
675#endif
676
677#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
21530947 678 if (!details->tlsAppLayerProtoNeg.isEmpty()) {
89c5ca0f 679 if (bumpMode == Ssl::bumpPeek)
3152460d 680 SSL_set_alpn_protos(ssl, (const unsigned char*)details->tlsAppLayerProtoNeg.rawContent(), details->tlsAppLayerProtoNeg.length());
89c5ca0f
CT
681 else {
682 static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
683 SSL_set_alpn_protos(ssl, supported_protos, sizeof(supported_protos));
684 }
685 }
686#endif
a95989ed
CT
687}
688
21530947 689#endif // USE_OPENSSL
f53969cc 690