]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/bio.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / ssl / bio.cc
1 /*
2 * Copyright (C) 1996-2016 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 "ssl/bio.h"
24
25 #if HAVE_OPENSSL_SSL_H
26 #include <openssl/ssl.h>
27 #endif
28
29 #if _SQUID_WINDOWS_
30 extern int socket_read_method(int, char *, int);
31 extern int socket_write_method(int, const char *, int);
32 #endif
33
34 /* BIO callbacks */
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);
42 /* SSL callbacks */
43 static void squid_ssl_info(const SSL *ssl, int where, int ret);
44
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 = {
49 BIO_TYPE_SOCKET,
50 "squid",
51 squid_bio_write,
52 squid_bio_read,
53 squid_bio_puts,
54 NULL, // squid_bio_gets not supported
55 squid_bio_ctrl,
56 squid_bio_create,
57 squid_bio_destroy,
58 NULL // squid_callback_ctrl not supported
59 };
60 #else
61 static BIO_METHOD *SquidMethods = NULL;
62 #endif
63
64 BIO *
65 Ssl::Bio::Create(const int fd, Ssl::Bio::Type type)
66 {
67 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
68 BIO_METHOD *useMethod = &SquidMethods;
69 #else
70 if (!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);
79 }
80 const BIO_METHOD *useMethod = SquidMethods;
81 #endif
82
83 if (BIO *bio = BIO_new(useMethod)) {
84 BIO_int_ctrl(bio, BIO_C_SET_FD, type, fd);
85 return bio;
86 }
87 return NULL;
88 }
89
90 void
91 Ssl::Bio::Link(SSL *ssl, BIO *bio)
92 {
93 SSL_set_bio(ssl, bio, bio); // cannot fail
94 SSL_set_info_callback(ssl, &squid_ssl_info); // does not provide diagnostic
95 }
96
97 Ssl::Bio::Bio(const int anFd): fd_(anFd)
98 {
99 debugs(83, 7, "Bio constructed, this=" << this << " FD " << fd_);
100 }
101
102 Ssl::Bio::~Bio()
103 {
104 debugs(83, 7, "Bio destructing, this=" << this << " FD " << fd_);
105 }
106
107 int Ssl::Bio::write(const char *buf, int size, BIO *table)
108 {
109 errno = 0;
110 #if _SQUID_WINDOWS_
111 const int result = socket_write_method(fd_, buf, size);
112 #else
113 const int result = default_write_method(fd_, buf, size);
114 #endif
115 const int xerrno = errno;
116 debugs(83, 5, "FD " << fd_ << " wrote " << result << " <= " << size);
117
118 BIO_clear_retry_flags(table);
119 if (result < 0) {
120 const bool ignoreError = ignoreErrno(xerrno) != 0;
121 debugs(83, 5, "error: " << xerrno << " ignored: " << ignoreError);
122 if (ignoreError)
123 BIO_set_retry_write(table);
124 }
125
126 return result;
127 }
128
129 int
130 Ssl::Bio::read(char *buf, int size, BIO *table)
131 {
132 errno = 0;
133 #if _SQUID_WINDOWS_
134 const int result = socket_read_method(fd_, buf, size);
135 #else
136 const int result = default_read_method(fd_, buf, size);
137 #endif
138 const int xerrno = errno;
139 debugs(83, 5, "FD " << fd_ << " read " << result << " <= " << size);
140
141 BIO_clear_retry_flags(table);
142 if (result < 0) {
143 const bool ignoreError = ignoreErrno(xerrno) != 0;
144 debugs(83, 5, "error: " << xerrno << " ignored: " << ignoreError);
145 if (ignoreError)
146 BIO_set_retry_read(table);
147 }
148
149 return result;
150 }
151
152 /// Called whenever the SSL connection state changes, an alert appears, or an
153 /// error occurs. See SSL_set_info_callback().
154 void
155 Ssl::Bio::stateChanged(const SSL *ssl, int where, int ret)
156 {
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.
160 // For example:
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");
165
166 debugs(83, 7, "FD " << fd_ << " now: 0x" << std::hex << where << std::dec << ' ' <<
167 SSL_state_string(ssl) << " (" << SSL_state_string_long(ssl) << ")");
168 }
169
170 void
171 Ssl::ClientBio::stateChanged(const SSL *ssl, int where, int ret)
172 {
173 Ssl::Bio::stateChanged(ssl, where, ret);
174 }
175
176 int
177 Ssl::ClientBio::write(const char *buf, int size, BIO *table)
178 {
179 if (holdWrite_) {
180 BIO_set_retry_write(table);
181 return 0;
182 }
183
184 return Ssl::Bio::write(buf, size, table);
185 }
186
187 int
188 Ssl::ClientBio::read(char *buf, int size, BIO *table)
189 {
190 if (holdRead_) {
191 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
192 BIO_set_retry_read(table);
193 return -1;
194 }
195
196 if (!rbuf.isEmpty()) {
197 int bytes = (size <= (int)rbuf.length() ? size : rbuf.length());
198 memcpy(buf, rbuf.rawContent(), bytes);
199 rbuf.consume(bytes);
200 return bytes;
201 } else
202 return Ssl::Bio::read(buf, size, table);
203
204 return -1;
205 }
206
207 Ssl::ServerBio::ServerBio(const int anFd):
208 Bio(anFd),
209 helloMsgSize(0),
210 helloBuild(false),
211 allowSplice(false),
212 allowBump(false),
213 holdWrite_(false),
214 holdRead_(true),
215 record_(false),
216 parsedHandshake(false),
217 parseError(false),
218 bumpMode_(bumpNone),
219 rbufConsumePos(0)
220 {
221 }
222
223 void
224 Ssl::ServerBio::stateChanged(const SSL *ssl, int where, int ret)
225 {
226 Ssl::Bio::stateChanged(ssl, where, ret);
227 }
228
229 void
230 Ssl::ServerBio::setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &aHello)
231 {
232 clientTlsDetails = details;
233 clientHelloMessage = aHello;
234 };
235
236 int
237 Ssl::ServerBio::read(char *buf, int size, BIO *table)
238 {
239 if (parsedHandshake) // done parsing TLS Hello
240 return readAndGive(buf, size, table);
241 else
242 return readAndParse(buf, size, table);
243 }
244
245 /// Read and give everything to OpenSSL.
246 int
247 Ssl::ServerBio::readAndGive(char *buf, const int size, BIO *table)
248 {
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);
253
254 if (record_) {
255 const int result = readAndBuffer(table);
256 if (result <= 0)
257 return result;
258 return giveBuffered(buf, size);
259 }
260
261 return Ssl::Bio::read(buf, size, table);
262 }
263
264 /// Read and give everything to our parser.
265 /// When/if parsing is finished (successfully or not), start giving to OpenSSL.
266 int
267 Ssl::ServerBio::readAndParse(char *buf, const int size, BIO *table)
268 {
269 const int result = readAndBuffer(table);
270 if (result <= 0)
271 return result;
272
273 try {
274 if (!parser_.parseHello(rbuf)) {
275 // need more data to finish parsing
276 BIO_set_retry_read(table);
277 return -1;
278 }
279 parsedHandshake = true; // done parsing (successfully)
280 }
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)
284 parseError = true;
285 }
286
287 if (holdRead_) {
288 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
289 BIO_set_retry_read(table);
290 return -1;
291 }
292
293 return giveBuffered(buf, size);
294 }
295
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.
298 int
299 Ssl::ServerBio::readAndBuffer(BIO *table)
300 {
301 char *space = rbuf.rawSpace(SQUID_TCP_SO_RCVBUF);
302 const int result = Ssl::Bio::read(space, rbuf.spaceSize(), table);
303 if (result <= 0)
304 return result;
305
306 rbuf.forceSize(rbuf.length() + result);
307 return result;
308 }
309
310 /// give previously buffered bytes to OpenSSL
311 /// returns the number of bytes given
312 int
313 Ssl::ServerBio::giveBuffered(char *buf, const int size)
314 {
315 if (rbuf.length() <= rbufConsumePos)
316 return -1; // buffered nothing yet
317
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");
323 return bytes;
324 }
325
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.
333 static bool
334 adjustSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, SBuf &helloMessage)
335 {
336 #if SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK
337 if (!ssl->s3) {
338 debugs(83, 5, "No SSLv3 data found!");
339 return false;
340 }
341
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);
346 #else
347 const bool requireCompression = details->compressionSupported;
348 #endif
349 if (requireCompression) {
350 debugs(83, 5, "Client Hello Data supports compression, but we do not!");
351 return false;
352 }
353
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!");
357 return false;
358 }
359 #endif
360
361 if (details->unsupportedExtensions) {
362 debugs(83, 5, "Client Hello contains extensions that we do not support!");
363 return false;
364 }
365
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);
369 return false;
370 }
371
372 /* Check whether all on-the-wire ciphers are supported by OpenSSL. */
373
374 const auto &wireCiphers = details->ciphers;
375 Security::TlsDetails::Ciphers::size_type ciphersToFind = wireCiphers.size();
376
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;
384 #else
385 const uint16_t scsvCipher = 0;
386 #endif
387
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))
394 --ciphersToFind;
395 }
396
397 if (ciphersToFind > 0 && scsvCipher && wireCiphers.find(scsvCipher) != wireCiphers.end())
398 --ciphersToFind;
399
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!");
403 return false;
404 }
405
406 debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
407
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();
414
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;
423 return true;
424 #else
425 return false;
426 #endif
427 }
428
429 int
430 Ssl::ServerBio::write(const char *buf, int size, BIO *table)
431 {
432
433 if (holdWrite_) {
434 debugs(83, 7, "postpone writing " << size << " bytes to SSL FD " << fd_);
435 BIO_set_retry_write(table);
436 return -1;
437 }
438
439 if (!helloBuild && (bumpMode_ == Ssl::bumpPeek || bumpMode_ == Ssl::bumpStare)) {
440 if (
441 buf[1] >= 3 //it is an SSL Version3 message
442 && buf[0] == 0x16 // and it is a Handshake/Hello message
443 ) {
444
445 //Hello message is the first message we write to server
446 assert(helloMsg.isEmpty());
447
448 auto ssl = fd_table[fd_].ssl.get();
449 if (ssl) {
450 if (bumpMode_ == Ssl::bumpPeek) {
451 if (adjustSSL(ssl, clientTlsDetails, clientHelloMessage))
452 allowBump = true;
453 allowSplice = true;
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*/
457 allowBump = true;
458 if (adjustSSL(ssl, clientTlsDetails, clientHelloMessage)) {
459 allowSplice = true;
460 helloMsg.append(clientHelloMessage);
461 debugs(83, 7, "SSL HELLO message for FD " << fd_ << ": Random number is adjusted for stare mode");
462 }
463 }
464 }
465 }
466 // If we do not build any hello message, copy the current
467 if (helloMsg.isEmpty())
468 helloMsg.append(buf, size);
469
470 helloBuild = true;
471 helloMsgSize = helloMsg.length();
472 //allowBump = true;
473
474 if (allowSplice) {
475 // Do not write yet.....
476 BIO_set_retry_write(table);
477 return -1;
478 }
479 }
480
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);
489 return -1;
490 }
491
492 // Sending hello message complete. Do not send more data for now...
493 holdWrite_ = true;
494
495 // spoof openSSL that we write what it ask us to write
496 return size;
497 } else
498 return Ssl::Bio::write(buf, size, table);
499 }
500
501 void
502 Ssl::ServerBio::flush(BIO *table)
503 {
504 if (!helloMsg.isEmpty()) {
505 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
506 helloMsg.consume(ret);
507 }
508 }
509
510 bool
511 Ssl::ServerBio::resumingSession()
512 {
513 return parser_.resumingSession;
514 }
515
516 /// initializes BIO table after allocation
517 static int
518 squid_bio_create(BIO *bi)
519 {
520 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
521 bi->init = 0; // set when we store Bio object and socket fd (BIO_C_SET_FD)
522 bi->num = 0;
523 bi->flags = 0;
524 #else
525 // No need to set more, openSSL initialize BIO memory to zero.
526 #endif
527
528 BIO_set_data(bi, NULL);
529 return 1;
530 }
531
532 /// cleans BIO table before deallocation
533 static int
534 squid_bio_destroy(BIO *table)
535 {
536 delete static_cast<Ssl::Bio*>(BIO_get_data(table));
537 BIO_set_data(table, NULL);
538 return 1;
539 }
540
541 /// wrapper for Bio::write()
542 static int
543 squid_bio_write(BIO *table, const char *buf, int size)
544 {
545 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
546 assert(bio);
547 return bio->write(buf, size, table);
548 }
549
550 /// wrapper for Bio::read()
551 static int
552 squid_bio_read(BIO *table, char *buf, int size)
553 {
554 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
555 assert(bio);
556 return bio->read(buf, size, table);
557 }
558
559 /// implements puts() via write()
560 static int
561 squid_bio_puts(BIO *table, const char *str)
562 {
563 assert(str);
564 return squid_bio_write(table, str, strlen(str));
565 }
566
567 /// other BIO manipulations (those without dedicated callbacks in BIO table)
568 static long
569 squid_bio_ctrl(BIO *table, int cmd, long arg1, void *arg2)
570 {
571 debugs(83, 5, table << ' ' << cmd << '(' << arg1 << ", " << arg2 << ')');
572
573 switch (cmd) {
574 case BIO_C_SET_FD: {
575 assert(arg2);
576 const int fd = *static_cast<int*>(arg2);
577 Ssl::Bio *bio;
578 if (arg1 == Ssl::Bio::BIO_TO_SERVER)
579 bio = new Ssl::ServerBio(fd);
580 else
581 bio = new Ssl::ClientBio(fd);
582 assert(!BIO_get_data(table));
583 BIO_set_data(table, bio);
584 BIO_set_init(table, 1);
585 return 0;
586 }
587
588 case BIO_C_GET_FD:
589 if (BIO_get_init(table)) {
590 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
591 assert(bio);
592 if (arg2)
593 *static_cast<int*>(arg2) = bio->fd();
594 return bio->fd();
595 }
596 return -1;
597
598 case BIO_CTRL_DUP:
599 // Should implemented if the SSL_dup openSSL API function
600 // used anywhere in squid.
601 return 0;
602
603 case BIO_CTRL_FLUSH:
604 if (BIO_get_init(table)) {
605 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
606 assert(bio);
607 bio->flush(table);
608 return 1;
609 }
610 return 0;
611
612 /* we may also need to implement these:
613 case BIO_CTRL_RESET:
614 case BIO_C_FILE_SEEK:
615 case BIO_C_FILE_TELL:
616 case BIO_CTRL_INFO:
617 case BIO_CTRL_GET_CLOSE:
618 case BIO_CTRL_SET_CLOSE:
619 case BIO_CTRL_PENDING:
620 case BIO_CTRL_WPENDING:
621 */
622 default:
623 return 0;
624
625 }
626
627 return 0; /* NOTREACHED */
628 }
629
630 /// wrapper for Bio::stateChanged()
631 static void
632 squid_ssl_info(const SSL *ssl, int where, int ret)
633 {
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);
637 }
638 }
639
640 void
641 applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode)
642 {
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());
654 }
655 #endif
656
657 if (!details->ciphers.empty()) {
658 SBuf strCiphers;
659 for (auto cipherId: details->ciphers) {
660 unsigned char cbytes[3];
661 cbytes[0] = (cipherId >> 8) & 0xFF;
662 cbytes[1] = cipherId & 0xFF;
663 cbytes[2] = 0;
664 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
665 const SSL_METHOD *method = SSLv23_method();
666 const SSL_CIPHER *c = method->get_cipher_by_char(cbytes);
667 #else
668 const SSL_CIPHER *c = SSL_CIPHER_find(ssl, cbytes);
669 #endif
670 if (c != NULL) {
671 if (!strCiphers.isEmpty())
672 strCiphers.append(":");
673 strCiphers.append(SSL_CIPHER_get_name(c));
674 }
675 }
676 if (!strCiphers.isEmpty())
677 SSL_set_cipher_list(ssl, strCiphers.c_str());
678 }
679
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);
683 #endif
684
685 #if defined(TLSEXT_STATUSTYPE_ocsp)
686 if (details->tlsStatusRequest)
687 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
688 #endif
689
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());
694 else {
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));
697 }
698 }
699 #endif
700 }
701
702 #endif // USE_OPENSSL
703