1 // ssl.c -- Support functions that find and load SSL support, if available
2 // Copyright (C) 2008-2010 Markus Gutschke <markus@shellinabox.com>
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License version 2 as
6 // published by the Free Software Foundation.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License along
14 // with this program; if not, write to the Free Software Foundation, Inc.,
15 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 // In addition to these license terms, the author grants the following
20 // If you modify this program, or any covered work, by linking or
21 // combining it with the OpenSSL project's OpenSSL library (or a
22 // modified version of that library), containing parts covered by the
23 // terms of the OpenSSL or SSLeay licenses, the author
24 // grants you additional permission to convey the resulting work.
25 // Corresponding Source for a non-source form of such a combination
26 // shall include the source code for the parts of OpenSSL used as well
27 // as that of the covered work.
29 // You may at your option choose to remove this additional permission from
30 // the work, or from any part of it.
32 // It is possible to build this program in a way that it loads OpenSSL
33 // libraries at run-time. If doing so, the following notices are required
34 // by the OpenSSL and SSLeay licenses:
36 // This product includes software developed by the OpenSSL Project
37 // for use in the OpenSSL Toolkit. (http://www.openssl.org/)
39 // This product includes cryptographic software written by Eric Young
40 // (eay@cryptsoft.com)
43 // The most up-to-date version of this program is always available from
44 // http://shellinabox.com
49 #define pthread_once x_pthread_once
50 #define pthread_sigmask x_pthread_sigmask
59 #include <sys/types.h>
63 #include "libhttp/ssl.h"
64 #include "libhttp/httpconnection.h"
65 #include "logging/logging.h"
68 #defined ATTR_UNUSED __attribute__((unused))
69 #defined UNUSED(x) do { } while (0)
72 #define UNUSED(x) do { (void)(x); } while (0)
76 #undef pthread_sigmask
78 #if defined(HAVE_OPENSSL) && !defined(OPENSSL_NO_TLSEXT) && \
79 defined(TLSEXT_NAMETYPE_host_name) && defined(SSL_TLSEXT_ERR_OK)
83 #if defined(HAVE_PTHREAD_H)
84 // Pthread support is optional. Only enable it, if the library has been
85 // linked into the program
87 #if defined(__linux__)
88 extern int pthread_once(pthread_once_t *, void (*)(void))__attribute__((weak));
90 extern int pthread_sigmask(int, const sigset_t *, sigset_t *)
91 __attribute__((weak));
95 #if defined(HAVE_DLOPEN)
96 // SSL support is optional. Only enable it, if the library can be loaded.
97 long (*BIO_ctrl)(BIO *, int, long, void *);
98 BIO_METHOD * (*BIO_f_buffer)(void);
99 void (*BIO_free_all)(BIO *);
100 BIO * (*BIO_new)(BIO_METHOD *);
101 BIO * (*BIO_new_socket)(int, int);
102 BIO * (*BIO_pop)(BIO *);
103 BIO * (*BIO_push)(BIO *, BIO *);
104 void (*ERR_clear_error)(void);
105 void (*ERR_clear_error)(void);
106 unsigned long (*ERR_peek_error)(void);
107 unsigned long (*ERR_peek_error)(void);
108 long (*SSL_CTX_callback_ctrl)(SSL_CTX *, int, void (*)(void));
109 int (*SSL_CTX_check_private_key)(const SSL_CTX *);
110 long (*SSL_CTX_ctrl)(SSL_CTX *, int, long, void *);
111 void (*SSL_CTX_free)(SSL_CTX *);
112 SSL_CTX * (*SSL_CTX_new)(SSL_METHOD *);
113 int (*SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
114 int (*SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *,
115 const unsigned char *, long);
116 int (*SSL_CTX_use_certificate_file)(SSL_CTX *, const char *, int);
117 int (*SSL_CTX_use_certificate_ASN1)(SSL_CTX *, long,
118 const unsigned char *);
119 long (*SSL_ctrl)(SSL *, int, long, void *);
120 void (*SSL_free)(SSL *);
121 int (*SSL_get_error)(const SSL *, int);
122 void * (*SSL_get_ex_data)(const SSL *, int);
123 BIO * (*SSL_get_rbio)(const SSL *);
124 const char * (*SSL_get_servername)(const SSL *, int);
125 BIO * (*SSL_get_wbio)(const SSL *);
126 int (*SSL_library_init)(void);
127 SSL * (*SSL_new)(SSL_CTX *);
128 int (*SSL_read)(SSL *, void *, int);
129 SSL_CTX * (*SSL_set_SSL_CTX)(SSL *, SSL_CTX *);
130 void (*SSL_set_accept_state)(SSL *);
131 void (*SSL_set_bio)(SSL *, BIO *, BIO *);
132 int (*SSL_set_ex_data)(SSL *, int, void *);
133 int (*SSL_shutdown)(SSL *);
134 int (*SSL_write)(SSL *, const void *, int);
135 SSL_METHOD * (*SSLv23_server_method)(void);
136 X509 * (*d2i_X509)(X509 **px, const unsigned char **in, int len);
137 void (*X509_free)(X509 *a);
140 static void sslDestroyCachedContext(void *ssl_, char *context_) {
141 struct SSLSupport *ssl = (struct SSLSupport *)ssl_;
142 SSL_CTX *context = (SSL_CTX *)context_;
143 #if defined(HAVE_OPENSSL)
144 if (context != ssl->sslContext) {
145 SSL_CTX_free(context);
149 check(!ssl->sslContext);
153 struct SSLSupport *newSSL(void) {
154 struct SSLSupport *ssl;
155 check(ssl = malloc(sizeof(struct SSLSupport)));
160 void initSSL(struct SSLSupport *ssl) {
161 ssl->enabled = serverSupportsSSL();
162 ssl->sslContext = NULL;
163 ssl->sniCertificatePattern = NULL;
164 ssl->generateMissing = 0;
165 initTrie(&ssl->sniContexts, sslDestroyCachedContext, ssl);
168 void destroySSL(struct SSLSupport *ssl) {
170 free(ssl->sniCertificatePattern);
171 destroyTrie(&ssl->sniContexts);
172 #if defined(HAVE_OPENSSL)
173 if (ssl->sslContext) {
174 dcheck(!ERR_peek_error());
175 SSL_CTX_free(ssl->sslContext);
178 check(!ssl->sslContext);
183 void deleteSSL(struct SSLSupport *ssl) {
188 #if defined(HAVE_OPENSSL) && defined(HAVE_DLOPEN)
189 static int maybeLoadCrypto(void) {
190 // Some operating systems cannot automatically load dependent dynamic
191 // libraries. As libssl.so can depend on libcrypto.so, we try to load
192 // it, iff we haven't tried loading it before and iff libssl.so does not
197 if (dlopen("libcrypto.so", RTLD_LAZY|RTLD_GLOBAL|RTLD_NOLOAD))
201 if (dlopen("libcrypto.so", RTLD_LAZY|RTLD_GLOBAL))
207 static void *loadSymbol(const char *lib, const char *fn) {
208 int err = NOINTR(dup(2));
210 int null = NOINTR(open("/dev/null", O_WRONLY));
212 NOINTR(dup2(null, 2));
216 void *dl = RTLD_DEFAULT;
217 void *rc = dlsym(dl, fn);
219 for (int i = 0; i < 2; i++) {
221 dl = dlopen(lib, RTLD_LAZY|RTLD_GLOBAL|RTLD_NOLOAD);
226 dl = dlopen(lib, RTLD_LAZY|RTLD_GLOBAL);
228 if (dl != NULL || !maybeLoadCrypto()) {
233 rc = dlsym(RTLD_DEFAULT, fn);
234 if (rc == NULL && maybeLoadCrypto()) {
235 rc = dlsym(RTLD_DEFAULT, fn);
240 NOINTR(dup2(err, 2));
246 static void loadSSL(void) {
247 check(!SSL_library_init);
250 void *avoid_gcc_warning_about_type_punning;
255 { { &BIO_ctrl }, "BIO_ctrl" },
256 { { &BIO_f_buffer }, "BIO_f_buffer" },
257 { { &BIO_free_all }, "BIO_free_all" },
258 { { &BIO_new }, "BIO_new" },
259 { { &BIO_new_socket }, "BIO_new_socket" },
260 { { &BIO_pop }, "BIO_pop" },
261 { { &BIO_push }, "BIO_push" },
262 { { &ERR_clear_error }, "ERR_clear_error" },
263 { { &ERR_clear_error }, "ERR_clear_error" },
264 { { &ERR_peek_error }, "ERR_peek_error" },
265 { { &ERR_peek_error }, "ERR_peek_error" },
266 { { &SSL_CTX_callback_ctrl }, "SSL_CTX_callback_ctrl" },
267 { { &SSL_CTX_check_private_key }, "SSL_CTX_check_private_key" },
268 { { &SSL_CTX_ctrl }, "SSL_CTX_ctrl" },
269 { { &SSL_CTX_free }, "SSL_CTX_free" },
270 { { &SSL_CTX_new }, "SSL_CTX_new" },
271 { { &SSL_CTX_use_PrivateKey_file }, "SSL_CTX_use_PrivateKey_file" },
272 { { &SSL_CTX_use_PrivateKey_ASN1 }, "SSL_CTX_use_PrivateKey_ASN1" },
273 { { &SSL_CTX_use_certificate_file },"SSL_CTX_use_certificate_file"},
274 { { &SSL_CTX_use_certificate_ASN1 },"SSL_CTX_use_certificate_ASN1"},
275 { { &SSL_ctrl }, "SSL_ctrl" },
276 { { &SSL_free }, "SSL_free" },
277 { { &SSL_get_error }, "SSL_get_error" },
278 { { &SSL_get_ex_data }, "SSL_get_ex_data" },
279 { { &SSL_get_rbio }, "SSL_get_rbio" },
281 { { &SSL_get_servername }, "SSL_get_servername" },
283 { { &SSL_get_wbio }, "SSL_get_wbio" },
284 { { &SSL_library_init }, "SSL_library_init" },
285 { { &SSL_new }, "SSL_new" },
286 { { &SSL_read }, "SSL_read" },
288 { { &SSL_set_SSL_CTX }, "SSL_set_SSL_CTX" },
290 { { &SSL_set_accept_state }, "SSL_set_accept_state" },
291 { { &SSL_set_bio }, "SSL_set_bio" },
292 { { &SSL_set_ex_data }, "SSL_set_ex_data" },
293 { { &SSL_shutdown }, "SSL_shutdown" },
294 { { &SSL_write }, "SSL_write" },
295 { { &SSLv23_server_method }, "SSLv23_server_method" },
296 { { &d2i_X509 }, "d2i_X509" },
297 { { &X509_free }, "X509_free" }
299 for (unsigned i = 0; i < sizeof(symbols)/sizeof(symbols[0]); i++) {
300 if (!(*symbols[i].var = loadSymbol("libssl.so", symbols[i].fn))) {
301 debug("Failed to load SSL support. Could not find \"%s\"",
303 for (unsigned j = 0; j < sizeof(symbols)/sizeof(symbols[0]); j++) {
304 *symbols[j].var = NULL;
310 dcheck(!ERR_peek_error());
311 debug("Loaded SSL suppport");
315 int serverSupportsSSL(void) {
316 #if defined(HAVE_OPENSSL) && !defined(HAVE_DLOPEN)
317 return SSL_library_init();
319 #if defined(HAVE_OPENSSL)
320 // We want to call loadSSL() exactly once. For single-threaded applications,
321 // this is straight-forward. For threaded applications, we need to call
322 // pthread_once(), instead. We perform run-time checks for whether we are
323 // single- or multi-threaded, so that the same code can be used.
324 // This currently only works on Linux.
325 #if defined(HAVE_PTHREAD_H) && defined(__linux__) && defined(__i386__)
326 if (!!&pthread_once) {
327 static pthread_once_t once = PTHREAD_ONCE_INIT;
328 pthread_once(&once, loadSSL);
332 static int initialized;
338 return !!SSL_library_init;
345 #if defined(HAVE_OPENSSL)
346 static void sslGenerateCertificate(const char *certificate,
347 const char *serverName) {
348 debug("Auto-generating missing certificate \"%s\" for \"%s\"",
349 certificate, serverName);
350 char *cmd = stringPrintf(NULL,
352 "exec 2>/dev/null </dev/null; "
354 "PATH=/usr/bin:/usr/sbin "
355 "openssl req -x509 -nodes -days 7300 -newkey rsa:1024 -keyout /dev/stdout "
356 "-out /dev/stdout -subj '/CN=%s/' | cat>'%s'",
357 serverName, certificate);
359 warn("Failed to generate self-signed certificate \"%s\"", certificate);
364 static const unsigned char *sslSecureReadASCIIFileToMem(int fd) {
366 size_t bufSize = inc;
369 check((buf = malloc(bufSize)) != NULL);
371 check(len < bufSize - 1);
372 ssize_t readLen = bufSize - len - 1;
373 ssize_t bytesRead = NOINTR(read(fd, buf + len, readLen));
377 if (bytesRead != readLen) {
381 // Instead of calling realloc(), allocate a new buffer, copy the data,
382 // and then clear the old buffer. This way, we are not accidentally
383 // leaving key material in memory.
384 unsigned char *newBuf;
385 check((newBuf = malloc(bufSize + inc)) != NULL);
386 memcpy(newBuf, buf, len);
387 memset(buf, 0, bufSize);
392 check(len < bufSize);
397 static const unsigned char *sslPEMtoASN1(const unsigned char *pem,
400 const unsigned char **eor) {
406 check((marker = stringPrintf(NULL, "-----BEGIN %s-----",record))!=NULL);
407 unsigned char *ptr = (unsigned char *)strstr((char *)pem, marker);
412 ptr += strlen(marker);
415 check((marker = stringPrintf(marker, "-----END %s-----",record))!=NULL);
416 unsigned char *end = (unsigned char *)strstr((char *)ptr, marker);
418 *eor = end + strlen(marker);
425 ssize_t maxSize = (((end - ptr)*6)+7)/8;
426 check((ret = malloc(maxSize)) != NULL);
427 unsigned char *out = ret;
431 unsigned char ch = *ptr++;
432 if (ch >= 'A' && ch <= 'Z') {
434 } else if (ch >= 'a' && ch <= 'z') {
436 } else if (ch >= '0' && ch <= '9') {
438 } else if (ch == '+') {
440 } else if (ch == '/') {
442 } else if (ch == '=') {
444 if ((ch = *ptr++) != '=' && ch > ' ') {
449 } else if (ch <= ' ') {
459 bits = (bits << 6) | ch;
462 *out++ = (bits >> (count -= 8)) & 0xFF;
465 check(out - ret <= maxSize);
470 static int sslSetCertificateFromFd(SSL_CTX *context, int fd) {
472 check(serverSupportsSSL());
474 const unsigned char *data = sslSecureReadASCIIFileToMem(fd);
475 check(!NOINTR(close(fd)));
476 long dataSize = (long)strlen((const char *)data);
477 long certSize, rsaSize, dsaSize, ecSize;
478 const unsigned char *record;
479 const unsigned char *cert = sslPEMtoASN1(data, "CERTIFICATE", &certSize,
481 const unsigned char *rsa = sslPEMtoASN1(data, "RSA PRIVATE KEY",&rsaSize,
483 const unsigned char *dsa = sslPEMtoASN1(data, "DSA PRIVATE KEY",&dsaSize,
485 const unsigned char *ec = sslPEMtoASN1(data, "EC PRIVATE KEY", &ecSize,
487 if (certSize && (rsaSize || dsaSize
492 SSL_CTX_use_certificate_ASN1(context, certSize, cert) &&
494 SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, context, rsa, rsaSize)) &&
496 SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_DSA, context, dsa, dsaSize))
500 SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_EC, context, ec, ecSize))
503 memset((char *)cert, 0, certSize);
506 cert = sslPEMtoASN1(record, "CERTIFICATE", &certSize,
510 const unsigned char *c = cert;
511 check(x509 = d2i_X509(NULL, &c, certSize));
512 memset((char *)cert, 0, certSize);
514 if (!SSL_CTX_add_extra_chain_cert(context, x509)) {
520 if (!record && SSL_CTX_check_private_key(context)) {
523 dcheck(!ERR_peek_error());
526 memset((char *)cert, 0, certSize);
529 memset((char *)data, 0, dataSize);
531 memset((char *)rsa, 0, rsaSize);
533 memset((char *)dsa, 0, dsaSize);
535 memset((char *)ec, 0, ecSize);
540 static int sslSetCertificateFromFile(SSL_CTX *context,
541 const char *filename) {
542 int fd = open(filename, O_RDONLY);
546 int rc = sslSetCertificateFromFd(context, fd);
552 static int sslSNICallback(SSL *sslHndl, int *al ATTR_UNUSED,
553 struct SSLSupport *ssl) {
555 check(!ERR_peek_error());
556 const char *name = SSL_get_servername(sslHndl,
557 TLSEXT_NAMETYPE_host_name);
558 if (name == NULL || !*name) {
559 return SSL_TLSEXT_ERR_OK;
561 struct HttpConnection *http =
562 (struct HttpConnection *)SSL_get_app_data(sslHndl);
563 debug("Received SNI callback for virtual host \"%s\" from \"%s:%d\"",
564 name, httpGetPeerName(http), httpGetPort(http));
566 check(serverName = malloc(strlen(name)+2));
570 if (ch >= 'A' && ch <= 'Z') {
572 } else if (ch != '\000' && ch != '.' && ch != '-' &&
573 (ch < '0' ||(ch > '9' && ch < 'A') || (ch > 'Z' &&
574 ch < 'a')|| ch > 'z')) {
578 serverName[++i] = ch;
585 return SSL_TLSEXT_ERR_OK;
587 SSL_CTX *context = (SSL_CTX *)getFromTrie(&ssl->sniContexts,
590 if (context == NULL) {
591 check(context = SSL_CTX_new(SSLv23_server_method()));
592 check(ssl->sniCertificatePattern);
593 char *certificate = stringPrintfUnchecked(NULL,
594 ssl->sniCertificatePattern,
596 if (sslSetCertificateFromFile(context, certificate) < 0) {
597 if (ssl->generateMissing) {
598 sslGenerateCertificate(certificate, serverName + 1);
600 // No need to check the certificate. If we fail to set it, we will use
601 // the default certificate, instead.
602 sslSetCertificateFromFile(context, certificate);
604 warn("Could not find matching certificate \"%s\" for \"%s\"",
605 certificate, serverName + 1);
606 SSL_CTX_free(context);
607 context = ssl->sslContext;
612 addToTrie(&ssl->sniContexts, serverName+1, (char *)context);
615 if (context != ssl->sslContext) {
616 check(SSL_set_SSL_CTX(sslHndl, context));
618 check(!ERR_peek_error());
619 return SSL_TLSEXT_ERR_OK;
623 #if defined(HAVE_OPENSSL) && !defined(HAVE_GETHOSTBYNAME_R)
624 // This is a not-thread-safe replacement for gethostbyname_r()
625 #define gethostbyname_r x_gethostbyname_r
626 static int gethostbyname_r(const char *name, struct hostent *ret,
627 char *buf ATTR_UNUSED, size_t buflen ATTR_UNUSED,
628 struct hostent **result, int *h_errnop) {
640 struct hostent *he = gethostbyname(name);
654 void sslSetCertificate(struct SSLSupport *ssl, const char *filename,
655 int autoGenerateMissing) {
656 #if defined(HAVE_OPENSSL)
657 check(serverSupportsSSL());
659 char *defaultCertificate;
660 check(defaultCertificate = strdup(filename));
661 char *ptr = strchr(defaultCertificate, '%');
663 check(!strchr(ptr+1, '%'));
664 check(ptr[1] == 's');
665 memmove(ptr, ptr + 2, strlen(ptr)-1);
668 // Try to set the default certificate. If necessary, (re-)generate it.
669 check(ssl->sslContext = SSL_CTX_new(SSLv23_server_method()));
670 if (autoGenerateMissing) {
671 if (sslSetCertificateFromFile(ssl->sslContext, defaultCertificate) < 0) {
672 char hostname[256], buf[4096];
673 check(!gethostname(hostname, sizeof(hostname)));
674 struct hostent he_buf, *he;
676 int ret = gethostbyname_r(hostname, &he_buf, buf, sizeof(buf), &he, &h_err);
677 if (!ret && he && he->h_name) {
678 sslGenerateCertificate(defaultCertificate, he->h_name);
681 warn("Error getting host information: \"%s\".", hstrerror(h_err));
683 sslGenerateCertificate(defaultCertificate, hostname);
686 goto valid_certificate;
689 if (sslSetCertificateFromFile(ssl->sslContext, defaultCertificate) < 0) {
690 fatal("Cannot read valid certificate from \"%s\". "
691 "Check file permissions and file format.", defaultCertificate);
694 free(defaultCertificate);
696 // Enable SNI support so that we can set a different certificate, if the
697 // client asked for it.
700 check(ssl->sniCertificatePattern = strdup(filename));
701 check(SSL_CTX_set_tlsext_servername_callback(ssl->sslContext,
703 check(SSL_CTX_set_tlsext_servername_arg(ssl->sslContext, ssl));
706 dcheck(!ERR_peek_error());
709 ssl->generateMissing = autoGenerateMissing;
713 // Convert the file descriptor to a human-readable format. Attempts to
714 // retrieve the original file name where possible.
716 static char *sslFdToFilename(int fd) {
719 check(proc = stringPrintf(NULL, "/proc/self/fd/%d", fd));
720 check(buf = malloc(len));
723 if ((i = readlink(proc, buf + 1, len-3)) < 0) {
726 check(buf = stringPrintf(NULL, "fd %d", fd));
728 } else if (i >= len-3) {
730 check(buf = realloc(buf, len));
733 check(i >= 0 && i < len);
736 if (!stat(buf + 1, &sb) && S_ISREG(sb.st_mode)) {
743 check(buf = stringPrintf(NULL, "fd %d", fd));
751 void sslSetCertificateFd(struct SSLSupport *ssl, int fd) {
753 check(ssl->sslContext = SSL_CTX_new(SSLv23_server_method()));
754 char *filename = sslFdToFilename(fd);
755 if (!sslSetCertificateFromFd(ssl->sslContext, fd)) {
756 fatal("Cannot read valid certificate from %s. Check file format.",
760 ssl->generateMissing = 0;
764 int sslEnable(struct SSLSupport *ssl, int enabled) {
765 int old = ssl->enabled;
766 ssl->enabled = enabled;
770 void sslBlockSigPipe(void) {
773 sigaddset(&set, SIGPIPE);
774 #if defined(HAVE_PTHREAD_H) && defined(__linux__) && defined(__i386__)
775 if (&pthread_sigmask) {
776 dcheck(!pthread_sigmask(SIG_BLOCK, &set, NULL));
780 dcheck(!sigprocmask(SIG_BLOCK, &set, NULL));
785 // This is a non-thread-safe replacement for sigwait()
786 static int dummysignalno;
787 static void dummysignal(int signo) {
788 dummysignalno = signo;
791 #define sigwait x_sigwait
792 static int sigwait(const sigset_t *set, int *sig) {
793 sigset_t mask, old_mask;
795 #if defined(HAVE_PTHREAD_H) && defined(__linux__) && defined(__i386__)
796 if (&pthread_sigmask) {
797 dcheck(!pthread_sigmask(SIG_BLOCK, &mask, &old_mask));
801 dcheck(!sigprocmask(SIG_BLOCK, &mask, &old_mask));
806 struct sigaction sa[NSIG];
807 memset(sa, 0, sizeof(sa));
808 sa->sa_handler = dummysignal;
809 for (int i = 1; i <= NSIG; i++) {
810 if (sigismember(set, i)) {
812 sigaction(i, sa, sa + i);
817 #if defined(HAVE_PTHREAD_H) && defined(__linux__) && defined(__i386__)
818 if (&pthread_sigmask) {
819 dcheck(!pthread_sigmask(SIG_SETMASK, &old_mask, NULL));
823 dcheck(!sigprocmask(SIG_BLOCK, &old_mask, NULL));
825 return dummysignalno;
829 int sslUnblockSigPipe(void) {
832 check(!sigpending(&set));
833 if (sigismember(&set, SIGPIPE)) {
834 sigwait(&set, &signum);
837 sigaddset(&set, SIGPIPE);
838 #if defined(HAVE_PTHREAD_H) && defined(__linux__) && defined(__i386__)
839 if (&pthread_sigmask) {
840 dcheck(!pthread_sigmask(SIG_UNBLOCK, &set, NULL));
844 dcheck(!sigprocmask(SIG_UNBLOCK, &set, NULL));
849 int sslPromoteToSSL(struct SSLSupport *ssl, SSL **sslHndl, int fd,
850 const char *buf, int len) {
851 #if defined(HAVE_OPENSSL)
855 dcheck(!ERR_peek_error());
856 dcheck(*sslHndl = SSL_new(ssl->sslContext));
857 if (*sslHndl == NULL) {
862 SSL_set_mode(*sslHndl, SSL_MODE_ENABLE_PARTIAL_WRITE);
863 BIO *writeBIO = BIO_new_socket(fd, 0);
864 BIO *readBIO = writeBIO;
866 readBIO = BIO_new(BIO_f_buffer());
867 BIO_push(readBIO, writeBIO);
868 check(BIO_set_buffer_read_data(readBIO, (char *)buf, len));
870 SSL_set_bio(*sslHndl, readBIO, writeBIO);
871 SSL_set_accept_state(*sslHndl);
872 dcheck(!ERR_peek_error());
882 void sslFreeHndl(SSL **sslHndl) {
883 #if defined(HAVE_OPENSSL)
885 // OpenSSL does not always correctly perform reference counting for stacked
886 // BIOs. This is particularly a problem if an SSL connection has two
887 // different BIOs for the read and the write end, with one being a stacked
888 // derivative of the other. Unfortunately, this is exactly the scenario
890 // As a work-around, we un-stack the BIOs prior to freeing the SSL
893 BIO *writeBIO, *readBIO;
894 check(writeBIO = SSL_get_wbio(*sslHndl));
895 check(readBIO = SSL_get_rbio(*sslHndl));
896 if (writeBIO != readBIO) {
897 if (readBIO->next_bio == writeBIO) {
898 // OK, that's exactly the bug we are looking for. We know how to
900 check(BIO_pop(readBIO) == writeBIO);
901 check(readBIO->references == 1);
902 check(writeBIO->references == 1);
903 check(!readBIO->next_bio);
904 check(!writeBIO->prev_bio);
905 } else if (readBIO->next_bio == writeBIO->next_bio &&
906 writeBIO->next_bio->prev_bio == writeBIO) {
907 // Things get even more confused, if the SSL handshake is aborted
909 // OpenSSL appears to internally stack a BIO onto the read end that
910 // does not get removed afterwards. We end up with the original
911 // socket BIO having two different BIOs prepended to it (one for
912 // reading and one for writing). In this case, not only is the
913 // reference count wrong, but the chain of next_bio/prev_bio pairs
914 // is corrupted, too.
916 check(sockBIO = BIO_pop(readBIO));
917 check(sockBIO == BIO_pop(writeBIO));
918 check(readBIO->references == 1);
919 check(writeBIO->references == 1);
920 check(sockBIO->references == 1);
921 check(!readBIO->next_bio);
922 check(!writeBIO->next_bio);
923 check(!sockBIO->prev_bio);
924 BIO_free_all(sockBIO);
926 // We do not know, how to fix this situation. Something must have
927 // changed in the OpenSSL internals. Either, this is a new bug, or
928 // somebody fixed the code in a way that we did not anticipate.
929 fatal("Unexpected corruption of OpenSSL data structures");
933 dcheck(!ERR_peek_error());