bio.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 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 "base/Raw.h"
18#include "comm.h"
19#include "fd.h"
20#include "fde.h"
21#include "globals.h"
22#include "ip/Address.h"
24#include "ssl/bio.h"
25
26#if _SQUID_WINDOWS_
27extern int socket_read_method(int, char *, int);
28extern int socket_write_method(int, const char *, int);
29#endif
30
31/* BIO callbacks */
32static int squid_bio_write(BIO *h, const char *buf, int num);
33static int squid_bio_read(BIO *h, char *buf, int size);
34static int squid_bio_puts(BIO *h, const char *str);
35//static int squid_bio_gets(BIO *h, char *str, int size);
36static long squid_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
37static int squid_bio_create(BIO *h);
38static int squid_bio_destroy(BIO *data);
39/* SSL callbacks */
40static void squid_ssl_info(const SSL *ssl, int where, int ret);
41
42#if HAVE_LIBCRYPTO_BIO_METH_NEW
43static BIO_METHOD *SquidMethods = nullptr;
44#else
47static BIO_METHOD SquidMethods = {
48 BIO_TYPE_SOCKET,
49 "squid",
53 nullptr, // squid_bio_gets not supported
57 NULL // squid_callback_ctrl not supported
58};
59#endif
60
61BIO *
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, nullptr);
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 nullptr;
85}
86
87void
88Ssl::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
94Ssl::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
104int 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
126int
127Ssl::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
151void
152Ssl::Bio::stateChanged(const SSL *ssl, int where, int)
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 abortReason(nullptr)
172{
173 renegotiations.configure(10*1000);
174}
175
176void
177Ssl::ClientBio::stateChanged(const SSL *ssl, int where, int ret)
178{
179 Ssl::Bio::stateChanged(ssl, where, ret);
180 // detect client-initiated renegotiations DoS (CVE-2011-1473)
181 if (where & SSL_CB_HANDSHAKE_START) {
182 const int reneg = renegotiations.count(1);
183
184 if (abortReason)
185 return; // already decided and informed the admin
186
187 if (reneg > RenegotiationsLimit) {
188 abortReason = "renegotiate requests flood";
189 debugs(83, DBG_IMPORTANT, "Terminating TLS connection [from " << fd_table[fd_].ipaddr << "] due to " << abortReason << ". This connection received " <<
190 reneg << " renegotiate requests in the last " <<
191 RenegotiationsWindow << " seconds (and " <<
192 renegotiations.remembered() << " requests total).");
193 }
194 }
195}
196
197int
198Ssl::ClientBio::write(const char *buf, int size, BIO *table)
199{
200 if (abortReason) {
201 debugs(83, 3, "BIO on FD " << fd_ << " is aborted");
202 BIO_clear_retry_flags(table);
203 return -1;
204 }
205
206 if (holdWrite_) {
207 BIO_set_retry_write(table);
208 return 0;
209 }
210
211 return Ssl::Bio::write(buf, size, table);
212}
213
214int
215Ssl::ClientBio::read(char *buf, int size, BIO *table)
216{
217 if (abortReason) {
218 debugs(83, 3, "BIO on FD " << fd_ << " is aborted");
219 BIO_clear_retry_flags(table);
220 return -1;
221 }
222
223 if (holdRead_) {
224 debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
225 BIO_set_retry_read(table);
226 return -1;
227 }
228
229 if (!rbuf.isEmpty()) {
230 int bytes = (size <= (int)rbuf.length() ? size : rbuf.length());
231 memcpy(buf, rbuf.rawContent(), bytes);
232 rbuf.consume(bytes);
233 return bytes;
234 } else
235 return Ssl::Bio::read(buf, size, table);
236
237 return -1;
238}
239
241 Bio(anFd),
242 helloMsgSize(0),
243 helloBuild(false),
244 allowSplice(false),
245 allowBump(false),
246 holdWrite_(false),
247 record_(false),
248 parsedHandshake(false),
249 parseError(false),
250 bumpMode_(bumpNone),
251 rbufConsumePos(0),
252 parser_(Security::HandshakeParser::fromServer)
253{
254}
255
256void
257Ssl::ServerBio::stateChanged(const SSL *ssl, int where, int ret)
258{
259 Ssl::Bio::stateChanged(ssl, where, ret);
260}
261
262void
264{
265 clientTlsDetails = details;
266 clientSentHello = aHello;
267};
268
269int
270Ssl::ServerBio::read(char *buf, int size, BIO *table)
271{
272 if (parsedHandshake) // done parsing TLS Hello
273 return readAndGive(buf, size, table);
274 else
275 return readAndParse(buf, size, table);
276}
277
279int
280Ssl::ServerBio::readAndGive(char *buf, const int size, BIO *table)
281{
282 // If we have unused buffered bytes, give those bytes to OpenSSL now,
283 // before reading more. TODO: Read if we have buffered less than size?
284 if (rbufConsumePos < rbuf.length())
285 return giveBuffered(buf, size);
286
287 if (record_) {
288 const int result = readAndBuffer(table);
289 if (result <= 0)
290 return result;
291 return giveBuffered(buf, size);
292 }
293
294 return Ssl::Bio::read(buf, size, table);
295}
296
299int
300Ssl::ServerBio::readAndParse(char *buf, const int size, BIO *table)
301{
302 const int result = readAndBuffer(table);
303 if (result <= 0)
304 return result;
305
306 try {
307 if (!parser_.parseHello(rbuf)) {
308 // need more data to finish parsing
309 BIO_set_retry_read(table);
310 return -1;
311 }
312 parsedHandshake = true; // done parsing (successfully)
313 }
314 catch (const std::exception &ex) {
315 debugs(83, 2, "parsing error on FD " << fd_ << ": " << ex.what());
316 parsedHandshake = true; // done parsing (due to an error)
317 parseError = true;
318 }
319
320 return giveBuffered(buf, size);
321}
322
325int
327{
328 char *space = rbuf.rawAppendStart(SQUID_TCP_SO_RCVBUF);
329 const int result = Ssl::Bio::read(space, SQUID_TCP_SO_RCVBUF, table);
330 if (result <= 0)
331 return result;
332
333 rbuf.rawAppendFinish(space, result);
334 return result;
335}
336
339int
341{
342 if (rbuf.length() <= rbufConsumePos)
343 return -1; // buffered nothing yet
344
345 const int unsent = rbuf.length() - rbufConsumePos;
346 const int bytes = (size <= unsent ? size : unsent);
347 memcpy(buf, rbuf.rawContent() + rbufConsumePos, bytes);
348 rbufConsumePos += bytes;
349 debugs(83, 7, bytes << "<=" << size << " bytes to OpenSSL");
350 return bytes;
351}
352
353int
354Ssl::ServerBio::write(const char *buf, int size, BIO *table)
355{
356
357 if (holdWrite_) {
358 debugs(83, 7, "postpone writing " << size << " bytes to SSL FD " << fd_);
359 BIO_set_retry_write(table);
360 return -1;
361 }
362
363 if (!helloBuild && (bumpMode_ == Ssl::bumpPeek || bumpMode_ == Ssl::bumpStare)) {
364 // We have not seen any bytes, so the buffer must start with an
365 // OpenSSL-generated TLSPlaintext record containing, for example, a
366 // ClientHello or an alert message. We check these assumptions before we
367 // substitute that record/message with clientSentHello.
368 // TODO: Move these checks to where we actually rely on them.
369 debugs(83, 7, "to-server" << Raw("TLSPlaintext", buf, size).hex());
370 Must(size >= 2); // enough for version and content_type checks below
371 Must(buf[1] >= 3); // record's version.major; determines buf[0] meaning
372 Must(20 <= buf[0] && buf[0] <= 23); // valid TLSPlaintext.content_type
373
374 //Hello message is the first message we write to server
375 assert(helloMsg.isEmpty());
376
377 if (bumpMode_ == Ssl::bumpPeek) {
378 // we should not be here if we failed to parse the client-sent ClientHello
379 Must(!clientSentHello.isEmpty());
380 allowSplice = true;
381 // Replace OpenSSL-generated ClientHello with client-sent one.
382 helloMsg.append(clientSentHello);
383 debugs(83, 7, "FD " << fd_ << ": Using client-sent ClientHello for peek mode");
384 } else { /*Ssl::bumpStare*/
385 allowBump = true;
386 }
387
388 // if we did not use the client-sent ClientHello, then use the OpenSSL-generated one
389 if (helloMsg.isEmpty())
390 helloMsg.append(buf, size);
391
392 helloBuild = true;
393 helloMsgSize = helloMsg.length();
394
395 if (allowSplice) {
396 // Do not write yet.....
397 BIO_set_retry_write(table);
398 return -1;
399 }
400 }
401
402 if (!helloMsg.isEmpty()) {
403 debugs(83, 7, "buffered write for FD " << fd_);
404 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
405 helloMsg.consume(ret);
406 if (!helloMsg.isEmpty()) {
407 // We need to retry sendind data.
408 // Say to openSSL to retry sending hello message
409 BIO_set_retry_write(table);
410 return -1;
411 }
412
413 // Sending hello message complete. Do not send more data for now...
414 holdWrite_ = true;
415
416 // spoof openSSL that we write what it ask us to write
417 return size;
418 } else
419 return Ssl::Bio::write(buf, size, table);
420}
421
422void
424{
425 if (!helloMsg.isEmpty()) {
426 int ret = Ssl::Bio::write(helloMsg.rawContent(), helloMsg.length(), table);
427 helloMsg.consume(ret);
428 }
429}
430
431bool
433{
434 return parser_.resumingSession;
435}
436
437bool
439{
440 return parser_.details->tlsSupportedVersion &&
441 Security::Tls1p3orLater(parser_.details->tlsSupportedVersion);
442}
443
445static int
447{
448#if !HAVE_LIBCRYPTO_BIO_GET_INIT
449 bi->init = 0; // set when we store Bio object and socket fd (BIO_C_SET_FD)
450 bi->num = 0;
451 bi->flags = 0;
452#else
453 // No need to set more, openSSL initialize BIO memory to zero.
454#endif
455
456 BIO_set_data(bi, nullptr);
457 return 1;
458}
459
461static int
463{
464 delete static_cast<Ssl::Bio*>(BIO_get_data(table));
465 BIO_set_data(table, nullptr);
466 return 1;
467}
468
470static int
471squid_bio_write(BIO *table, const char *buf, int size)
472{
473 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
474 assert(bio);
475 return bio->write(buf, size, table);
476}
477
479static int
480squid_bio_read(BIO *table, char *buf, int size)
481{
482 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
483 assert(bio);
484 return bio->read(buf, size, table);
485}
486
488static int
489squid_bio_puts(BIO *table, const char *str)
490{
491 assert(str);
492 return squid_bio_write(table, str, strlen(str));
493}
494
496static long
497squid_bio_ctrl(BIO *table, int cmd, long arg1, void *arg2)
498{
499 debugs(83, 5, table << ' ' << cmd << '(' << arg1 << ", " << arg2 << ')');
500
501 switch (cmd) {
502 case BIO_C_SET_FD: {
503 assert(arg2);
504 const int fd = *static_cast<int*>(arg2);
505 Ssl::Bio *bio;
506 if (arg1 == Security::Io::BIO_TO_SERVER)
507 bio = new Ssl::ServerBio(fd);
508 else
509 bio = new Ssl::ClientBio(fd);
510 assert(!BIO_get_data(table));
511 BIO_set_data(table, bio);
512 BIO_set_init(table, 1);
513 return 0;
514 }
515
516 case BIO_C_GET_FD:
517 if (BIO_get_init(table)) {
518 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
519 assert(bio);
520 if (arg2)
521 *static_cast<int*>(arg2) = bio->fd();
522 return bio->fd();
523 }
524 return -1;
525
526 case BIO_CTRL_DUP:
527 // Should implemented if the SSL_dup openSSL API function
528 // used anywhere in squid.
529 return 0;
530
531 case BIO_CTRL_FLUSH:
532 if (BIO_get_init(table)) {
533 Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table));
534 assert(bio);
535 bio->flush(table);
536 return 1;
537 }
538 return 0;
539
540 /* we may also need to implement these:
541 case BIO_CTRL_RESET:
542 case BIO_C_FILE_SEEK:
543 case BIO_C_FILE_TELL:
544 case BIO_CTRL_INFO:
545 case BIO_CTRL_GET_CLOSE:
546 case BIO_CTRL_SET_CLOSE:
547 case BIO_CTRL_PENDING:
548 case BIO_CTRL_WPENDING:
549 */
550 default:
551 return 0;
552
553 }
554
555 return 0; /* NOTREACHED */
556}
557
559static void
560squid_ssl_info(const SSL *ssl, int where, int ret)
561{
562 if (BIO *table = SSL_get_rbio(ssl)) {
563 if (Ssl::Bio *bio = static_cast<Ssl::Bio*>(BIO_get_data(table)))
564 bio->stateChanged(ssl, where, ret);
565 }
566}
567
568void
570{
571 // To increase the possibility for bumping after peek mode selection or
572 // splicing after stare mode selection it is good to set the
573 // SSL protocol version.
574 // The SSL_set_ssl_method is wrong here because it will restrict the
575 // permitted transport version to be identical to the version used in the
576 // ClientHello message.
577 // For example will prevent comunnicating with a tls1.0 server if the
578 // client sent and tlsv1.2 Hello message.
579#if defined(TLSEXT_NAMETYPE_host_name)
580 if (!details->serverName.isEmpty()) {
581 SSL_set_tlsext_host_name(ssl, details->serverName.c_str());
582 }
583#endif
584
585 if (!details->ciphers.empty()) {
586 SBuf strCiphers;
587 for (auto cipherId: details->ciphers) {
588 unsigned char cbytes[3];
589 cbytes[0] = (cipherId >> 8) & 0xFF;
590 cbytes[1] = cipherId & 0xFF;
591 cbytes[2] = 0;
592 if (const auto c = SSL_CIPHER_find(ssl, cbytes)) {
593 if (!strCiphers.isEmpty())
594 strCiphers.append(":");
595 strCiphers.append(SSL_CIPHER_get_name(c));
596 }
597 }
598 if (!strCiphers.isEmpty())
599 SSL_set_cipher_list(ssl, strCiphers.c_str());
600 }
601
602#if defined(SSL_OP_NO_COMPRESSION) /* XXX: OpenSSL 0.9.8k lacks SSL_OP_NO_COMPRESSION */
603 if (!details->compressionSupported)
604 SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
605#endif
606
607#if defined(SSL_OP_NO_TLSv1_3)
608 // avoid "inappropriate fallback" OpenSSL error messages
609 if (details->tlsSupportedVersion && Security::Tls1p2orEarlier(details->tlsSupportedVersion))
610 SSL_set_options(ssl, SSL_OP_NO_TLSv1_3);
611#endif
612
613#if defined(TLSEXT_STATUSTYPE_ocsp)
614 if (details->tlsStatusRequest)
615 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
616#endif
617
618#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
619 if (!details->tlsAppLayerProtoNeg.isEmpty()) {
620 if (bumpMode == Ssl::bumpPeek)
621 SSL_set_alpn_protos(ssl, (const unsigned char*)details->tlsAppLayerProtoNeg.rawContent(), details->tlsAppLayerProtoNeg.length());
622 else {
623 static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
624 SSL_set_alpn_protos(ssl, supported_protos, sizeof(supported_protos));
625 }
626 }
627#endif
628}
629
630#endif // USE_OPENSSL
631
int size
Definition: ModDevPoll.cc:75
#define Must(condition)
Definition: TextException.h:75
#define assert(EX)
Definition: assert.h:17
static int squid_bio_puts(BIO *h, const char *str)
implements puts() via write()
Definition: bio.cc:489
static void squid_ssl_info(const SSL *ssl, int where, int ret)
wrapper for Bio::stateChanged()
Definition: bio.cc:560
static int squid_bio_create(BIO *h)
initializes BIO table after allocation
Definition: bio.cc:446
static int squid_bio_write(BIO *h, const char *buf, int num)
wrapper for Bio::write()
Definition: bio.cc:471
static int squid_bio_destroy(BIO *data)
cleans BIO table before deallocation
Definition: bio.cc:462
void applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode)
Definition: bio.cc:569
static BIO_METHOD SquidMethods
Definition: bio.cc:47
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:497
static int squid_bio_read(BIO *h, char *buf, int size)
wrapper for Bio::read()
Definition: bio.cc:480
void configure(double horizonSeconds)
0=remember nothing; -1=forget nothing; new value triggers clear()
Definition: Raw.h:21
Definition: SBuf.h:94
const char * c_str()
Definition: SBuf.cc:516
bool isEmpty() const
Definition: SBuf.h:431
SBuf & append(const SBuf &S)
Definition: SBuf.cc:185
BIO source and sink node, handling socket I/O and monitoring SSL state.
Definition: bio.h:34
int fd() const
The SSL socket descriptor.
Definition: bio.h:49
const int fd_
the SSL socket we are reading and writing
Definition: bio.h:63
virtual void stateChanged(const SSL *ssl, int where, int ret)
Definition: bio.cc:152
virtual int write(const char *buf, int size, BIO *table)
Writes the given data to socket.
Definition: bio.cc:104
virtual ~Bio()
Definition: bio.cc:99
static void Link(SSL *ssl, BIO *bio)
Tells ssl connection to use BIO and monitor state via stateChanged()
Definition: bio.cc:88
static BIO * Create(const int fd, Security::Io::Type type)
Definition: bio.cc:62
virtual void flush(BIO *)
Definition: bio.h:47
virtual int read(char *buf, int size, BIO *table)
Reads data from socket.
Definition: bio.cc:127
Bio(const int anFd)
Definition: bio.cc:94
FadingCounter renegotiations
client requested renegotiations limit control
Definition: bio.h:101
int write(const char *buf, int size, BIO *table) override
The ClientBio version of the Ssl::Bio::write method.
Definition: bio.cc:198
void stateChanged(const SSL *ssl, int where, int ret) override
Definition: bio.cc:177
ClientBio(const int anFd)
Definition: bio.cc:167
int read(char *buf, int size, BIO *table) override
Definition: bio.cc:215
int write(const char *buf, int size, BIO *table) override
Definition: bio.cc:354
void flush(BIO *table) override
Definition: bio.cc:423
ServerBio(const int anFd)
Definition: bio.cc:240
void setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &hello)
Sets the random number to use in client SSL HELLO message.
Definition: bio.cc:263
void stateChanged(const SSL *ssl, int where, int ret) override
The ServerBio version of the Ssl::Bio::stateChanged method.
Definition: bio.cc:257
bool encryptedCertificates() const
Definition: bio.cc:438
bool resumingSession()
Definition: bio.cc:432
int readAndParse(char *buf, const int size, BIO *table)
Definition: bio.cc:300
int read(char *buf, int size, BIO *table) override
Definition: bio.cc:270
int readAndGive(char *buf, const int size, BIO *table)
Read and give everything to OpenSSL.
Definition: bio.cc:280
int readAndBuffer(BIO *table)
Definition: bio.cc:326
int giveBuffered(char *buf, const int size)
Definition: bio.cc:340
int ignoreErrno(int ierrno)
Definition: comm.cc:1440
#define DBG_IMPORTANT
Definition: Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
int default_read_method(int, char *, int)
Definition: fd.cc:129
int default_write_method(int, const char *, int)
Definition: fd.cc:135
#define fd_table
Definition: fde.h:189
const char * bumpMode(int bm)
Definition: support.h:138
BumpMode
Definition: support.h:126
@ bumpPeek
Definition: support.h:126
@ bumpNone
Definition: support.h:126
@ bumpStare
Definition: support.h:126
@ BIO_TO_SERVER
Definition: forward.h:170
Network/connection security abstraction layer.
Definition: Connection.h:34
bool Tls1p3orLater(const AnyP::ProtocolVersion &p)
whether the given TLS/SSL protocol is TLS v1.3 or later
Definition: Handshake.h:160
bool Tls1p2orEarlier(const AnyP::ProtocolVersion &p)
whether the given TLS/SSL protocol is TLS v1.2 or earlier, including SSL
Definition: Handshake.h:153
const SSL_CIPHER * SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr)
Definition: openssl.h:139
void * BIO_get_data(BIO *table)
Definition: openssl.h:62
void BIO_set_init(BIO *table, int init)
Definition: openssl.h:74
void BIO_set_data(BIO *table, void *data)
Definition: openssl.h:68
int BIO_get_init(BIO *table)
Definition: openssl.h:82
int unsigned int
Definition: stub_fd.cc:19
#define NULL
Definition: types.h:145

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors