]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/bio.cc
merge from trunk-r14768
[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 /// Initialization structure for the BIO table with
46 /// Squid-specific methods and BIO method wrappers.
47 static 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
60 BIO *
61 Ssl::Bio::Create(const int fd, Ssl::Bio::Type type)
62 {
63 if (BIO *bio = BIO_new(&SquidMethods)) {
64 BIO_int_ctrl(bio, BIO_C_SET_FD, type, fd);
65 return bio;
66 }
67 return NULL;
68 }
69
70 void
71 Ssl::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
77 Ssl::Bio::Bio(const int anFd): fd_(anFd)
78 {
79 debugs(83, 7, "Bio constructed, this=" << this << " FD " << fd_);
80 }
81
82 Ssl::Bio::~Bio()
83 {
84 debugs(83, 7, "Bio destructing, this=" << this << " FD " << fd_);
85 }
86
87 int 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
109 int
110 Ssl::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().
134 void
135 Ssl::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
146 debugs(83, 7, "FD " << fd_ << " now: 0x" << std::hex << where << std::dec << ' ' <<
147 SSL_state_string(ssl) << " (" << SSL_state_string_long(ssl) << ")");
148 }
149
150 bool
151 Ssl::ClientBio::isClientHello(int state)
152 {
153 return (
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
159 );
160 }
161
162 void
163 Ssl::ClientBio::stateChanged(const SSL *ssl, int where, int ret)
164 {
165 Ssl::Bio::stateChanged(ssl, where, ret);
166 }
167
168 int
169 Ssl::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
179 int
180 Ssl::ClientBio::read(char *buf, int size, BIO *table)
181 {
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
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);
195
196 return -1;
197 }
198
199 Ssl::ServerBio::ServerBio(const int anFd):
200 Bio(anFd),
201 helloMsgSize(0),
202 helloBuild(false),
203 allowSplice(false),
204 allowBump(false),
205 holdWrite_(false),
206 holdRead_(true),
207 record_(false),
208 parsedHandshake(false),
209 parseError(false),
210 bumpMode_(bumpNone),
211 rbufConsumePos(0)
212 {
213 }
214
215 void
216 Ssl::ServerBio::stateChanged(const SSL *ssl, int where, int ret)
217 {
218 Ssl::Bio::stateChanged(ssl, where, ret);
219 }
220
221 void
222 Ssl::ServerBio::setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &aHello)
223 {
224 clientTlsDetails = details;
225 clientHelloMessage = aHello;
226 };
227
228 int
229 Ssl::ServerBio::read(char *buf, int size, BIO *table)
230 {
231 if (parsedHandshake) // done parsing TLS Hello
232 return readAndGive(buf, size, table);
233 else
234 return readAndParse(buf, size, table);
235 }
236
237 /// Read and give everything to OpenSSL.
238 int
239 Ssl::ServerBio::readAndGive(char *buf, const int size, BIO *table)
240 {
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);
245
246 if (record_) {
247 const int result = readAndBuffer(table);
248 if (result <= 0)
249 return result;
250 return giveBuffered(buf, size);
251 }
252
253 return Ssl::Bio::read(buf, size, table);
254 }
255
256 /// Read and give everything to our parser.
257 /// When/if parsing is finished (successfully or not), start giving to OpenSSL.
258 int
259 Ssl::ServerBio::readAndParse(char *buf, const int size, BIO *table)
260 {
261 const int result = readAndBuffer(table);
262 if (result <= 0)
263 return result;
264
265 try {
266 if (!parser_.parseHello(rbuf)) {
267 // need more data to finish parsing
268 BIO_set_retry_read(table);
269 return -1;
270 }
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)
276 parseError = true;
277 }
278
279 if (holdRead_) {
280 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
281 BIO_set_retry_read(table);
282 return -1;
283 }
284
285 return giveBuffered(buf, size);
286 }
287
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.
290 int
291 Ssl::ServerBio::readAndBuffer(BIO *table)
292 {
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;
297
298 rbuf.forceSize(rbuf.length() + result);
299 return result;
300 }
301
302 /// give previously buffered bytes to OpenSSL
303 /// returns the number of bytes given
304 int
305 Ssl::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;
316 }
317
318 // This function makes the required checks to examine if the client hello
319 // message is compatible with the features provided by OpenSSL toolkit.
320 // If the features are compatible and can be supported it tries to rewrite SSL
321 // structure members, to replace the hello message created by openSSL, with the
322 // web client SSL hello message.
323 // This is mostly possible in the cases where the web client uses openSSL
324 // library similar with this one used by squid.
325 static bool
326 adjustSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, SBuf &helloMessage)
327 {
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
334 // If the client supports compression but our context does not support
335 // we can not adjust.
336 #if !defined(OPENSSL_NO_COMP)
337 const bool requireCompression = (details->compressionSupported && ssl->ctx->comp_methods == nullptr);
338 #else
339 const bool requireCompression = details->compressionSupported;
340 #endif
341 if (requireCompression) {
342 debugs(83, 5, "Client Hello Data supports compression, but we do not!");
343 return false;
344 }
345
346 #if !defined(SSL_TLSEXT_HB_ENABLED)
347 if (details->doHeartBeats) {
348 debugs(83, 5, "Client Hello Data supports HeartBeats but we do not support!");
349 return false;
350 }
351 #endif
352
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.
373 #if defined(TLSEXT_TYPE_renegotiate)
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;
378 #endif
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;
387 }
388
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!");
395 return false;
396 }
397
398 debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
399
400 //Adjust ssl structure data.
401 // We need to fix the random in SSL struct:
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();
406
407 size_t mainHelloSize = helloMessage.length() - 5;
408 const char *mainHello = helloMessage.rawContent() + 5;
409 assert((size_t)ssl->init_buf->max > mainHelloSize);
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;
415 return true;
416 #else
417 return false;
418 #endif
419 }
420
421 int
422 Ssl::ServerBio::write(const char *buf, int size, BIO *table)
423 {
424
425 if (holdWrite_) {
426 debugs(83, 7, "postpone writing " << size << " bytes to SSL FD " << fd_);
427 BIO_set_retry_write(table);
428 return -1;
429 }
430
431 if (!helloBuild && (bumpMode_ == Ssl::bumpPeek || bumpMode_ == Ssl::bumpStare)) {
432 if (
433 buf[1] >= 3 //it is an SSL Version3 message
434 && buf[0] == 0x16 // and it is a Handshake/Hello message
435 ) {
436
437 //Hello message is the first message we write to server
438 assert(helloMsg.isEmpty());
439
440 auto ssl = fd_table[fd_].ssl.get();
441 if (ssl) {
442 if (bumpMode_ == Ssl::bumpPeek) {
443 if (adjustSSL(ssl, clientTlsDetails, clientHelloMessage))
444 allowBump = true;
445 allowSplice = true;
446 helloMsg.append(clientHelloMessage);
447 debugs(83, 7, "SSL HELLO message for FD " << fd_ << ": Random number is adjusted for peek mode");
448 } else { /*Ssl::bumpStare*/
449 allowBump = true;
450 if (adjustSSL(ssl, clientTlsDetails, clientHelloMessage)) {
451 allowSplice = true;
452 helloMsg.append(clientHelloMessage);
453 debugs(83, 7, "SSL HELLO message for FD " << fd_ << ": Random number is adjusted for stare mode");
454 }
455 }
456 }
457 }
458 // If we do not build any hello message, copy the current
459 if (helloMsg.isEmpty())
460 helloMsg.append(buf, size);
461
462 helloBuild = true;
463 helloMsgSize = helloMsg.length();
464 //allowBump = true;
465
466 if (allowSplice) {
467 // Do not write yet.....
468 BIO_set_retry_write(table);
469 return -1;
470 }
471 }
472
473 if (!helloMsg.isEmpty()) {
474 debugs(83, 7, "buffered write for FD " << fd_);
475 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
476 helloMsg.consume(ret);
477 if (!helloMsg.isEmpty()) {
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...
485 holdWrite_ = true;
486
487 // spoof openSSL that we write what it ask us to write
488 return size;
489 } else
490 return Ssl::Bio::write(buf, size, table);
491 }
492
493 void
494 Ssl::ServerBio::flush(BIO *table)
495 {
496 if (!helloMsg.isEmpty()) {
497 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
498 helloMsg.consume(ret);
499 }
500 }
501
502 bool
503 Ssl::ServerBio::resumingSession()
504 {
505 return parser_.resumingSession;
506 }
507
508 /// initializes BIO table after allocation
509 static int
510 squid_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
520 static int
521 squid_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()
529 static int
530 squid_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()
538 static int
539 squid_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()
547 static int
548 squid_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)
555 static long
556 squid_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);
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);
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
585 case BIO_CTRL_DUP:
586 // Should implemented if the SSL_dup openSSL API function
587 // used anywhere in squid.
588 return 0;
589
590 case BIO_CTRL_FLUSH:
591 if (table->init) {
592 Ssl::Bio *bio = static_cast<Ssl::Bio*>(table->ptr);
593 assert(bio);
594 bio->flush(table);
595 return 1;
596 }
597 return 0;
598
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 */
609 default:
610 return 0;
611
612 }
613
614 return 0; /* NOTREACHED */
615 }
616
617 /// wrapper for Bio::stateChanged()
618 static void
619 squid_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
627 void
628 applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode)
629 {
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.
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.
636 // For example will prevent comunnicating with a tls1.0 server if the
637 // client sent and tlsv1.2 Hello message.
638 #if defined(TLSEXT_NAMETYPE_host_name)
639 if (!details->serverName.isEmpty()) {
640 SSL_set_tlsext_host_name(ssl, details->serverName.c_str());
641 }
642 #endif
643
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;
651 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
652 const SSL_METHOD *method = TLS_method();
653 #else
654 const SSL_METHOD *method = SSLv23_method();
655 #endif
656 const SSL_CIPHER *c = method->get_cipher_by_char(cbytes);
657 if (c != NULL) {
658 if (!strCiphers.isEmpty())
659 strCiphers.append(":");
660 strCiphers.append(c->name);
661 }
662 }
663 if (!strCiphers.isEmpty())
664 SSL_set_cipher_list(ssl, strCiphers.c_str());
665 }
666
667 #if defined(SSL_OP_NO_COMPRESSION) /* XXX: OpenSSL 0.9.8k lacks SSL_OP_NO_COMPRESSION */
668 if (!details->compressionSupported)
669 SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
670 #endif
671
672 #if defined(TLSEXT_STATUSTYPE_ocsp)
673 if (details->tlsStatusRequest)
674 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
675 #endif
676
677 #if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
678 if (!details->tlsAppLayerProtoNeg.isEmpty()) {
679 if (bumpMode == Ssl::bumpPeek)
680 SSL_set_alpn_protos(ssl, (const unsigned char*)details->tlsAppLayerProtoNeg.rawContent(), details->tlsAppLayerProtoNeg.length());
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
687 }
688
689 #endif // USE_OPENSSL
690