Issue #384: compatibility with OpenSSL 1.1.0
* Direct usage of BIO struct members is removed for new versions of OpenSSL. * Workaround for double BIO free in SSL_free() was updated to work with new and old OpenSSL versions. * Note that this patch only fixes compatibilty when building with configure option "--disable-runtime-loading" (like it is done for Debia package.).
This commit is contained in:
parent
d4bd77ca45
commit
d0d8c58882
2 changed files with 25 additions and 16 deletions
|
@ -100,6 +100,7 @@ BIO_METHOD * (*BIO_f_buffer)(void);
|
||||||
void (*BIO_free_all)(BIO *);
|
void (*BIO_free_all)(BIO *);
|
||||||
BIO * (*BIO_new)(BIO_METHOD *);
|
BIO * (*BIO_new)(BIO_METHOD *);
|
||||||
BIO * (*BIO_new_socket)(int, int);
|
BIO * (*BIO_new_socket)(int, int);
|
||||||
|
BIO * (*BIO_next)(BIO *);
|
||||||
BIO * (*BIO_pop)(BIO *);
|
BIO * (*BIO_pop)(BIO *);
|
||||||
BIO * (*BIO_push)(BIO *, BIO *);
|
BIO * (*BIO_push)(BIO *, BIO *);
|
||||||
#if defined(HAVE_OPENSSL_EC)
|
#if defined(HAVE_OPENSSL_EC)
|
||||||
|
@ -280,6 +281,7 @@ static void loadSSL(void) {
|
||||||
{ { &BIO_free_all }, "BIO_free_all" },
|
{ { &BIO_free_all }, "BIO_free_all" },
|
||||||
{ { &BIO_new }, "BIO_new" },
|
{ { &BIO_new }, "BIO_new" },
|
||||||
{ { &BIO_new_socket }, "BIO_new_socket" },
|
{ { &BIO_new_socket }, "BIO_new_socket" },
|
||||||
|
{ { &BIO_next }, "BIO_next" },
|
||||||
{ { &BIO_pop }, "BIO_pop" },
|
{ { &BIO_pop }, "BIO_pop" },
|
||||||
{ { &BIO_push }, "BIO_push" },
|
{ { &BIO_push }, "BIO_push" },
|
||||||
{ { &ERR_clear_error }, "ERR_clear_error" },
|
{ { &ERR_clear_error }, "ERR_clear_error" },
|
||||||
|
@ -1013,6 +1015,14 @@ int sslPromoteToSSL(struct SSLSupport *ssl, SSL **sslHndl, int fd,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIO *sslGetNextBIO(BIO *b) {
|
||||||
|
#if OPENSSL_VERSION_NUMBER <= 0x10100000L
|
||||||
|
return b->next_bio;
|
||||||
|
#else
|
||||||
|
return BIO_next(b);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void sslFreeHndl(SSL **sslHndl) {
|
void sslFreeHndl(SSL **sslHndl) {
|
||||||
#if defined(HAVE_OPENSSL)
|
#if defined(HAVE_OPENSSL)
|
||||||
if (*sslHndl) {
|
if (*sslHndl) {
|
||||||
|
@ -1020,24 +1030,23 @@ void sslFreeHndl(SSL **sslHndl) {
|
||||||
// BIOs. This is particularly a problem if an SSL connection has two
|
// BIOs. This is particularly a problem if an SSL connection has two
|
||||||
// different BIOs for the read and the write end, with one being a stacked
|
// different BIOs for the read and the write end, with one being a stacked
|
||||||
// derivative of the other. Unfortunately, this is exactly the scenario
|
// derivative of the other. Unfortunately, this is exactly the scenario
|
||||||
// that we set up.
|
// that we set up with call to "BIO_push(readBIO, writeBIO)" in function
|
||||||
|
// "sslPromoteToSSL()".
|
||||||
// As a work-around, we un-stack the BIOs prior to freeing the SSL
|
// As a work-around, we un-stack the BIOs prior to freeing the SSL
|
||||||
// connection.
|
// connection.
|
||||||
|
debug("[ssl] Freeing SSL handle.");
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
BIO *writeBIO, *readBIO;
|
BIO *writeBIO, *readBIO;
|
||||||
check(writeBIO = SSL_get_wbio(*sslHndl));
|
check(writeBIO = SSL_get_wbio(*sslHndl));
|
||||||
check(readBIO = SSL_get_rbio(*sslHndl));
|
check(readBIO = SSL_get_rbio(*sslHndl));
|
||||||
if (writeBIO != readBIO) {
|
if (writeBIO != readBIO) {
|
||||||
if (readBIO->next_bio == writeBIO) {
|
if (sslGetNextBIO(readBIO) == writeBIO) {
|
||||||
// OK, that's exactly the bug we are looking for. We know how to
|
// OK, that's exactly the bug we are looking for. We know that
|
||||||
// fix it.
|
// writeBIO needs to be removed from readBIO chain.
|
||||||
|
debug("[ssl] Removing stacked write BIO!");
|
||||||
check(BIO_pop(readBIO) == writeBIO);
|
check(BIO_pop(readBIO) == writeBIO);
|
||||||
check(readBIO->references == 1);
|
check(!sslGetNextBIO(readBIO));
|
||||||
check(writeBIO->references == 1);
|
} else if (sslGetNextBIO(readBIO) == sslGetNextBIO(writeBIO)) {
|
||||||
check(!readBIO->next_bio);
|
|
||||||
check(!writeBIO->prev_bio);
|
|
||||||
} else if (readBIO->next_bio == writeBIO->next_bio &&
|
|
||||||
writeBIO->next_bio->prev_bio == writeBIO) {
|
|
||||||
// Things get even more confused, if the SSL handshake is aborted
|
// Things get even more confused, if the SSL handshake is aborted
|
||||||
// prematurely.
|
// prematurely.
|
||||||
// OpenSSL appears to internally stack a BIO onto the read end that
|
// OpenSSL appears to internally stack a BIO onto the read end that
|
||||||
|
@ -1046,15 +1055,13 @@ void sslFreeHndl(SSL **sslHndl) {
|
||||||
// reading and one for writing). In this case, not only is the
|
// reading and one for writing). In this case, not only is the
|
||||||
// reference count wrong, but the chain of next_bio/prev_bio pairs
|
// reference count wrong, but the chain of next_bio/prev_bio pairs
|
||||||
// is corrupted, too.
|
// is corrupted, too.
|
||||||
|
warn("[ssl] Removing stacked socket BIO!");
|
||||||
BIO *sockBIO;
|
BIO *sockBIO;
|
||||||
check(sockBIO = BIO_pop(readBIO));
|
check(sockBIO = BIO_pop(readBIO));
|
||||||
check(sockBIO == BIO_pop(writeBIO));
|
check(sockBIO == BIO_pop(writeBIO));
|
||||||
check(readBIO->references == 1);
|
check(!sslGetNextBIO(readBIO));
|
||||||
check(writeBIO->references == 1);
|
check(!sslGetNextBIO(writeBIO));
|
||||||
check(sockBIO->references == 1);
|
check(!sslGetNextBIO(sockBIO));
|
||||||
check(!readBIO->next_bio);
|
|
||||||
check(!writeBIO->next_bio);
|
|
||||||
check(!sockBIO->prev_bio);
|
|
||||||
BIO_free_all(sockBIO);
|
BIO_free_all(sockBIO);
|
||||||
} else {
|
} else {
|
||||||
// We do not know, how to fix this situation. Something must have
|
// We do not know, how to fix this situation. Something must have
|
||||||
|
|
|
@ -82,6 +82,7 @@ extern BIO_METHOD *(*x_BIO_f_buffer)(void);
|
||||||
extern void (*x_BIO_free_all)(BIO *);
|
extern void (*x_BIO_free_all)(BIO *);
|
||||||
extern BIO *(*x_BIO_new)(BIO_METHOD *);
|
extern BIO *(*x_BIO_new)(BIO_METHOD *);
|
||||||
extern BIO *(*x_BIO_new_socket)(int, int);
|
extern BIO *(*x_BIO_new_socket)(int, int);
|
||||||
|
extern BIO *(*x_BIO_next)(BIO *);
|
||||||
extern BIO *(*x_BIO_pop)(BIO *);
|
extern BIO *(*x_BIO_pop)(BIO *);
|
||||||
extern BIO *(*x_BIO_push)(BIO *, BIO *);
|
extern BIO *(*x_BIO_push)(BIO *, BIO *);
|
||||||
#if defined(HAVE_OPENSSL_EC)
|
#if defined(HAVE_OPENSSL_EC)
|
||||||
|
@ -131,6 +132,7 @@ extern void *(*x_SSL_COMP_get_compression_methods)(void);
|
||||||
#define BIO_free_all x_BIO_free_all
|
#define BIO_free_all x_BIO_free_all
|
||||||
#define BIO_new x_BIO_new
|
#define BIO_new x_BIO_new
|
||||||
#define BIO_new_socket x_BIO_new_socket
|
#define BIO_new_socket x_BIO_new_socket
|
||||||
|
#define BIO_next x_BIO_next
|
||||||
#define BIO_pop x_BIO_pop
|
#define BIO_pop x_BIO_pop
|
||||||
#define BIO_push x_BIO_push
|
#define BIO_push x_BIO_push
|
||||||
#define EC_KEY_free x_EC_KEY_free
|
#define EC_KEY_free x_EC_KEY_free
|
||||||
|
|
Loading…
Reference in a new issue