On Mon, Jun 13, 2016 at 10:07:51PM +0200, Bert Huijben wrote: > > > > -----Original Message----- > > From: James McCoy [mailto:vega.ja...@gmail.com] On Behalf Of James > > McCoy > > Sent: zondag 12 juni 2016 20:56 > > To: dev@serf.apache.org > > Subject: [PATCH] Prepare serf for OpenSSL 1.1 release > > > > OpenSSL is preparing a 1.1.0 release which introduces API and ABI > > incompatibilities (described in an in-progress[0] wiki page). > > > > [0]: https://wiki.openssl.org/index.php/1.1_API_Changes > > > > A rebuild[1] of all Debian packages using OpenSSL found that serf is > > affected by these changes, specifically making BIO/BIO_METHOD opaque and > > removing the need for the locking functions[2]. > > > > [1]: https://breakpoint.cc/openssl-1.1-rebuild-2016-05-29/ > > [2]: > > https://github.com/openssl/openssl/blob/dae00d631fdaed48d88c454864abbd6 > > ce99c63d6/include/openssl/crypto.h#L209-L216 > > > > The attached patches fix the build and pass the test suites both with > > OpenSSL 1.0.2h and a pre-release of OpenSSL 1.1.0, but more eyes are > > always good. > > Hi, > > I had a quick look at this patch. The patch looks like it fixes the > issues you identified. I'm guessing the patch introduces a minor > memory leak via the new calls to BIO_meth_new(), as there is no code > path that destroys these now.
Thanks for the review and spotting that. Should be fixed in the updated patch. > For trunk I would prefer a patch with the USE_OPENSSL_1_1_API macro > defined the other way around. Newer OpenSSL 1.X versions will most > likely all use the new code path, while only 1.0 (and 0.x) will use > the legacy code path. Ok. I've changed the macro to USE_LEGACY_OPENSSL and adjusted accordingly. > > I'm including patches for both branches/1.3.x and trunk since there's a > > bit of divergence between the two. > > > > I tried to look at OpenSSL 1.1.0 earlier myself, but as my build > depends on Subversion dependencies I got into a few other problems > earlier. I got an easy workaround for APR, but Cyrus Sasl was a > different story. Do you know if there is already a patch for that > package? Not that I've seen yet. Upstream is pretty quiet and I know the folks on the Debian side were looking for more help in general, so I'm not sure if they'll have time to help. I have a few other things on my plate, but if there's still a need when I get past that I'll take a look at cyrus-sasl. Cheers, -- James GPG Key: 4096R/91BF BF4D 6956 BD5D F7B7 2D23 DFE6 91AE 331B A3DB
Index: branches/1.3.x/buckets/ssl_buckets.c =================================================================== --- branches/1.3.x/buckets/ssl_buckets.c (revision 1748479) +++ branches/1.3.x/buckets/ssl_buckets.c (working copy) @@ -52,7 +52,11 @@ #define APR_ARRAY_PUSH(ary,type) (*((type *)apr_array_push(ary))) #endif +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +#define USE_OPENSSL_1_1_API +#endif + /* * Here's an overview of the SSL bucket's relationship to OpenSSL and serf. * @@ -140,6 +144,7 @@ SSL_CTX *ctx; SSL *ssl; BIO *bio; + BIO_METHOD *biom; serf_ssl_stream_t encrypt; serf_ssl_stream_t decrypt; @@ -232,10 +237,28 @@ } #endif +static void bio_set_data(BIO *bio, void *data) +{ +#ifdef USE_OPENSSL_1_1_API + BIO_set_data(bio, data); +#else + bio->ptr = data; +#endif +} + +static void *bio_get_data(BIO *bio) +{ +#ifdef USE_OPENSSL_1_1_API + return BIO_get_data(bio); +#else + return bio->ptr; +#endif +} + /* Returns the amount read. */ static int bio_bucket_read(BIO *bio, char *in, int inlen) { - serf_ssl_context_t *ctx = bio->ptr; + serf_ssl_context_t *ctx = bio_get_data(bio); const char *data; apr_status_t status; apr_size_t len; @@ -279,7 +302,7 @@ /* Returns the amount written. */ static int bio_bucket_write(BIO *bio, const char *in, int inl) { - serf_ssl_context_t *ctx = bio->ptr; + serf_ssl_context_t *ctx = bio_get_data(bio); serf_bucket_t *tmp; serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write called for %d bytes\n", @@ -307,7 +330,7 @@ /* Returns the amount read. */ static int bio_file_read(BIO *bio, char *in, int inlen) { - apr_file_t *file = bio->ptr; + apr_file_t *file = bio_get_data(bio); apr_status_t status; apr_size_t len; @@ -329,7 +352,7 @@ /* Returns the amount written. */ static int bio_file_write(BIO *bio, const char *in, int inl) { - apr_file_t *file = bio->ptr; + apr_file_t *file = bio_get_data(bio); apr_size_t nbytes; BIO_clear_retry_flags(bio); @@ -342,7 +365,7 @@ static int bio_file_gets(BIO *bio, char *in, int inlen) { - apr_file_t *file = bio->ptr; + apr_file_t *file = bio_get_data(bio); apr_status_t status; status = apr_file_gets(in, inlen, file); @@ -358,10 +381,16 @@ static int bio_bucket_create(BIO *bio) { +#ifdef USE_OPENSSL_1_1_API + BIO_set_shutdown(bio, 1); + BIO_set_init(bio, 1); + BIO_set_data(bio, NULL); +#else bio->shutdown = 1; bio->init = 1; bio->num = -1; bio->ptr = NULL; +#endif return 1; } @@ -395,6 +424,7 @@ return ret; } +#ifndef USE_OPENSSL_1_1_API static BIO_METHOD bio_bucket_method = { BIO_TYPE_MEM, "Serf SSL encryption and decryption buckets", @@ -424,7 +454,56 @@ NULL /* sslc does not have the callback_ctrl field */ #endif }; +#endif +static BIO_METHOD *bio_meth_bucket_new(void) +{ + BIO_METHOD *biom = NULL; + +#ifdef USE_OPENSSL_1_1_API + biom = BIO_meth_new(BIO_TYPE_MEM, + "Serf SSL encryption and decryption buckets"); + if (biom) { + BIO_meth_set_write(biom, bio_bucket_write); + BIO_meth_set_read(biom, bio_bucket_read); + BIO_meth_set_ctrl(biom, bio_bucket_ctrl); + BIO_meth_set_create(biom, bio_bucket_create); + BIO_meth_set_destroy(biom, bio_bucket_destroy); + } +#else + biom = &bio_bucket_method; +#endif + + return biom; +} + +static BIO_METHOD *bio_meth_file_new(void) +{ + BIO_METHOD *biom = NULL; + +#ifdef USE_OPENSSL_1_1_API + biom = BIO_meth_new(BIO_TYPE_FILE, + "Wrapper around APR file structures"); + BIO_meth_set_write(biom, bio_file_write); + BIO_meth_set_read(biom, bio_file_read); + BIO_meth_set_gets(biom, bio_file_gets); + BIO_meth_set_ctrl(biom, bio_bucket_ctrl); + BIO_meth_set_create(biom, bio_bucket_create); + BIO_meth_set_destroy(biom, bio_bucket_destroy); +#else + biom = &bio_file_method; +#endif + + return biom; +} + +static void bio_meth_free(BIO_METHOD *biom) +{ +#ifdef USE_OPENSSL_1_1_API + BIO_meth_free(biom); +#endif +} + typedef enum san_copy_t { EscapeNulAndCopy = 0, ErrorOnNul = 1, @@ -973,7 +1052,7 @@ return status; } -#if APR_HAS_THREADS +#if APR_HAS_THREADS && !defined(USE_OPENSSL_1_1_API) static apr_pool_t *ssl_pool; static apr_thread_mutex_t **ssl_locks; @@ -1060,7 +1139,7 @@ val = apr_atomic_cas32(&have_init_ssl, INIT_BUSY, INIT_UNINITIALIZED); if (!val) { -#if APR_HAS_THREADS +#if APR_HAS_THREADS && !defined(USE_OPENSSL_1_1_API) int i, numlocks; #endif @@ -1077,13 +1156,17 @@ } #endif +#ifdef USE_OPENSSL_1_1_API + OPENSSL_malloc_init(); +#else CRYPTO_malloc_init(); +#endif ERR_load_crypto_strings(); SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); -#if APR_HAS_THREADS +#if APR_HAS_THREADS && !defined(USE_OPENSSL_1_1_API) numlocks = CRYPTO_num_locks(); apr_pool_create(&ssl_pool, NULL); ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks); @@ -1136,6 +1219,7 @@ const char *cert_path; apr_file_t *cert_file; BIO *bio; + BIO_METHOD *biom; PKCS12 *p12; int i; int retrying_success = 0; @@ -1161,8 +1245,9 @@ continue; } - bio = BIO_new(&bio_file_method); - bio->ptr = cert_file; + biom = bio_meth_file_new(); + bio = BIO_new(biom); + bio_set_data(bio, cert_file); ctx->cert_path = cert_path; p12 = d2i_PKCS12_bio(bio, NULL); @@ -1172,6 +1257,7 @@ if (i == 1) { PKCS12_free(p12); + bio_meth_free(biom); ctx->cached_cert = *cert; ctx->cached_cert_pw = *pkey; if (!retrying_success && ctx->cert_cache_pool) { @@ -1207,6 +1293,7 @@ i = PKCS12_parse(p12, password, pkey, cert, NULL); if (i == 1) { PKCS12_free(p12); + bio_meth_free(biom); ctx->cached_cert = *cert; ctx->cached_cert_pw = *pkey; if (!retrying_success && ctx->cert_cache_pool) { @@ -1234,6 +1321,7 @@ } } PKCS12_free(p12); + bio_meth_free(biom); return 0; } else { @@ -1241,6 +1329,7 @@ ERR_GET_FUNC(err), ERR_GET_REASON(err)); PKCS12_free(p12); + bio_meth_free(biom); } } } @@ -1335,8 +1424,9 @@ disable_compression(ssl_ctx); ssl_ctx->ssl = SSL_new(ssl_ctx->ctx); - ssl_ctx->bio = BIO_new(&bio_bucket_method); - ssl_ctx->bio->ptr = ssl_ctx; + ssl_ctx->biom = bio_meth_bucket_new(); + ssl_ctx->bio = BIO_new(ssl_ctx->biom); + bio_set_data(ssl_ctx->bio, ssl_ctx); SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio); @@ -1379,6 +1469,7 @@ /* SSL_free implicitly frees the underlying BIO. */ SSL_free(ssl_ctx->ssl); + bio_meth_free(ssl_ctx->biom); SSL_CTX_free(ssl_ctx->ctx); serf_bucket_mem_free(ssl_ctx->allocator, ssl_ctx); Index: branches/1.3.x/test/server/test_sslserver.c =================================================================== --- branches/1.3.x/test/server/test_sslserver.c (revision 1748479) +++ branches/1.3.x/test/server/test_sslserver.c (working copy) @@ -27,6 +27,10 @@ #include <openssl/ssl.h> #include <openssl/err.h> +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +#define USE_OPENSSL_1_1_API +#endif + static int init_done = 0; typedef struct ssl_context_t { @@ -35,6 +39,7 @@ SSL_CTX* ctx; SSL* ssl; BIO *bio; + BIO_METHOD *biom; } ssl_context_t; @@ -45,12 +50,36 @@ return strlen(buf); } +static void bio_set_data(BIO *bio, void *data) +{ +#ifdef USE_OPENSSL_1_1_API + BIO_set_data(bio, data); +#else + bio->ptr = data; +#endif +} + +static void *bio_get_data(BIO *bio) +{ +#ifdef USE_OPENSSL_1_1_API + return BIO_get_data(bio); +#else + return bio->ptr; +#endif +} + static int bio_apr_socket_create(BIO *bio) { +#ifdef USE_OPENSSL_1_1_API + BIO_set_shutdown(bio, 1); + BIO_set_init(bio, 1); + BIO_set_data(bio, NULL); +#else bio->shutdown = 1; bio->init = 1; bio->num = -1; bio->ptr = NULL; +#endif return 1; } @@ -88,7 +117,7 @@ static int bio_apr_socket_read(BIO *bio, char *in, int inlen) { apr_size_t len = inlen; - serv_ctx_t *serv_ctx = bio->ptr; + serv_ctx_t *serv_ctx = bio_get_data(bio); apr_status_t status; BIO_clear_retry_flags(bio); @@ -114,7 +143,7 @@ static int bio_apr_socket_write(BIO *bio, const char *in, int inlen) { apr_size_t len = inlen; - serv_ctx_t *serv_ctx = bio->ptr; + serv_ctx_t *serv_ctx = bio_get_data(bio); apr_status_t status = apr_socket_send(serv_ctx->client_sock, in, &len); @@ -129,6 +158,7 @@ } +#ifndef USE_OPENSSL_1_1_API static BIO_METHOD bio_apr_socket_method = { BIO_TYPE_SOCKET, "APR sockets", @@ -143,7 +173,28 @@ NULL /* sslc does not have the callback_ctrl field */ #endif }; +#endif +static BIO_METHOD *bio_meth_apr_socket_new(void) +{ + BIO_METHOD *biom = NULL; + +#ifdef USE_OPENSSL_1_1_API + biom = BIO_meth_new(BIO_TYPE_SOCKET, "APR sockets"); + if (biom) { + BIO_meth_set_write(biom, bio_apr_socket_write); + BIO_meth_set_read(biom, bio_apr_socket_read); + BIO_meth_set_ctrl(biom, bio_apr_socket_ctrl); + BIO_meth_set_create(biom, bio_apr_socket_create); + BIO_meth_set_destroy(biom, bio_apr_socket_destroy); + } +#else + biom = &bio_apr_socket_method; +#endif + + return biom; +} + static int validate_client_certificate(int preverify_ok, X509_STORE_CTX *ctx) { serf__log(TEST_VERBOSE, __FILE__, "validate_client_certificate called, " @@ -177,7 +228,11 @@ /* Init OpenSSL globally */ if (!init_done) { +#ifdef USE_OPENSSL_1_1_API + OPENSSL_malloc_init(); +#else CRYPTO_malloc_init(); +#endif ERR_load_crypto_strings(); SSL_load_error_strings(); SSL_library_init(); @@ -234,8 +289,9 @@ SSL_CTX_set_mode(ssl_ctx->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); - ssl_ctx->bio = BIO_new(&bio_apr_socket_method); - ssl_ctx->bio->ptr = serv_ctx; + ssl_ctx->biom = bio_meth_apr_socket_new(); + ssl_ctx->bio = BIO_new(ssl_ctx->biom); + bio_set_data(ssl_ctx->bio, serv_ctx); init_ssl(serv_ctx); } @@ -388,8 +444,12 @@ ssl_context_t *ssl_ctx = servctx->ssl_ctx; if (ssl_ctx) { - if (ssl_ctx->ssl) + if (ssl_ctx->ssl) { SSL_clear(ssl_ctx->ssl); +#ifdef USE_OPENSSL_1_1_API + BIO_meth_free(ssl_ctx->biom); +#endif + } SSL_CTX_free(ssl_ctx->ctx); }
Index: trunk/buckets/ssl_buckets.c =================================================================== --- trunk/buckets/ssl_buckets.c (revision 1748479) +++ trunk/buckets/ssl_buckets.c (working copy) @@ -49,7 +49,12 @@ #define APR_ARRAY_PUSH(ary,type) (*((type *)apr_array_push(ary))) #endif +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L +#define USE_LEGACY_OPENSSL +#define X509_STORE_get0_param(store) store->param +#endif + /* * Here's an overview of the SSL bucket's relationship to OpenSSL and serf. * @@ -128,6 +133,7 @@ SSL_CTX *ctx; SSL *ssl; BIO *bio; + BIO_METHOD *biom; serf_ssl_stream_t encrypt; serf_ssl_stream_t decrypt; @@ -294,7 +300,11 @@ #endif /* The server asked to renegotiate the SSL session. */ +#ifndef USE_LEGACY_OPENSSL + if (SSL_get_state(s) == TLS_ST_SW_HELLO_REQ) { +#else if (SSL_state(s) == SSL_ST_RENEGOTIATE) { +#endif serf_ssl_context_t *ssl_ctx = SSL_get_app_data(s); ssl_ctx->renegotiation = 1; @@ -310,10 +320,28 @@ } +static void bio_set_data(BIO *bio, void *data) +{ +#ifndef USE_LEGACY_OPENSSL + BIO_set_data(bio, data); +#else + bio->ptr = data; +#endif +} + +static void *bio_get_data(BIO *bio) +{ +#ifndef USE_LEGACY_OPENSSL + return BIO_get_data(bio); +#else + return bio->ptr; +#endif +} + /* Returns the amount read. */ static int bio_bucket_read(BIO *bio, char *in, int inlen) { - serf_ssl_context_t *ctx = bio->ptr; + serf_ssl_context_t *ctx = bio_get_data(bio); const char *data; apr_status_t status; apr_size_t len; @@ -356,7 +384,7 @@ /* Returns the amount written. */ static int bio_bucket_write(BIO *bio, const char *in, int inl) { - serf_ssl_context_t *ctx = bio->ptr; + serf_ssl_context_t *ctx = bio_get_data(bio); serf_bucket_t *tmp; serf__log(LOGLVL_DEBUG, LOGCOMP_SSL, __FILE__, ctx->config, @@ -384,7 +412,7 @@ /* Returns the amount read. */ static int bio_file_read(BIO *bio, char *in, int inlen) { - apr_file_t *file = bio->ptr; + apr_file_t *file = bio_get_data(bio); apr_status_t status; apr_size_t len; @@ -406,7 +434,7 @@ /* Returns the amount written. */ static int bio_file_write(BIO *bio, const char *in, int inl) { - apr_file_t *file = bio->ptr; + apr_file_t *file = bio_get_data(bio); apr_size_t nbytes; BIO_clear_retry_flags(bio); @@ -419,7 +447,7 @@ static int bio_file_gets(BIO *bio, char *in, int inlen) { - apr_file_t *file = bio->ptr; + apr_file_t *file = bio_get_data(bio); apr_status_t status; status = apr_file_gets(in, inlen, file); @@ -435,10 +463,16 @@ static int bio_bucket_create(BIO *bio) { +#ifndef USE_LEGACY_OPENSSL + BIO_set_shutdown(bio, 1); + BIO_set_init(bio, 1); + BIO_set_data(bio, NULL); +#else bio->shutdown = 1; bio->init = 1; bio->num = -1; bio->ptr = NULL; +#endif return 1; } @@ -472,6 +506,7 @@ return ret; } +#ifdef USE_LEGACY_OPENSSL static BIO_METHOD bio_bucket_method = { BIO_TYPE_MEM, "Serf SSL encryption and decryption buckets", @@ -501,7 +536,57 @@ NULL /* sslc does not have the callback_ctrl field */ #endif }; +#endif +static BIO_METHOD *bio_meth_bucket_new(void) +{ + BIO_METHOD *biom = NULL; + +#ifndef USE_LEGACY_OPENSSL + biom = BIO_meth_new(BIO_TYPE_MEM, + "Serf SSL encryption and decryption buckets"); + if (biom) { + BIO_meth_set_write(biom, bio_bucket_write); + BIO_meth_set_read(biom, bio_bucket_read); + BIO_meth_set_ctrl(biom, bio_bucket_ctrl); + BIO_meth_set_create(biom, bio_bucket_create); + BIO_meth_set_destroy(biom, bio_bucket_destroy); + } +#else + biom = &bio_bucket_method; +#endif + + return biom; +} + +static BIO_METHOD *bio_meth_file_new(void) +{ + BIO_METHOD *biom = NULL; + +#ifndef USE_LEGACY_OPENSSL + biom = BIO_meth_new(BIO_TYPE_FILE, "Wrapper around APR file structures"); + if (biom) { + BIO_meth_set_write(biom, bio_file_write); + BIO_meth_set_read(biom, bio_file_read); + BIO_meth_set_gets(biom, bio_file_gets); + BIO_meth_set_ctrl(biom, bio_bucket_ctrl); + BIO_meth_set_create(biom, bio_bucket_create); + BIO_meth_set_destroy(biom, bio_bucket_destroy); + } +#else + biom = &bio_file_method; +#endif + + return biom; +} + +static void bio_meth_free(BIO_METHOD *biom) +{ +#ifndef USE_LEGACY_OPENSSL + BIO_meth_free(biom); +#endif +} + #ifndef OPENSSL_NO_TLSEXT /* Callback called when the server response has some OCSP info. Returns 1 if the application accepts the OCSP response as successful, @@ -511,7 +596,6 @@ { serf_ssl_context_t *ctx = (serf_ssl_context_t*)baton; OCSP_RESPONSE *response; - OCSP_RESPBYTES *rb; const unsigned char *resp_der; int len; long resp_status; @@ -533,10 +617,8 @@ return SSL_TLSEXT_ERR_ALERT_FATAL; } - rb = response->responseBytes; - /* Did the server get a valid response from the OCSP responder */ - resp_status = ASN1_ENUMERATED_get(response->responseStatus); + resp_status = OCSP_response_status(response); switch (resp_status) { case OCSP_RESPONSE_STATUS_SUCCESSFUL: break; @@ -1028,8 +1110,12 @@ /* Once we got through the initial handshake, we should have received the ALPN information if there is such information. */ ctx->handshake_finished = SSL_is_init_finished(ctx->ssl) +#ifndef USE_LEGACY_OPENSSL + || (SSL_get_state(ctx->ssl) == TLS_ST_OK); +#else || (SSL_state(ctx->ssl) & SSL_CB_HANDSHAKE_DONE); +#endif /* Call the protocol callback as soon as possible as this triggers pipelining data for the selected protocol. */ @@ -1226,7 +1312,7 @@ return status; } -#if APR_HAS_THREADS +#if APR_HAS_THREADS && defined(USE_LEGACY_OPENSSL) static apr_pool_t *ssl_pool; static apr_thread_mutex_t **ssl_locks; @@ -1313,7 +1399,7 @@ val = apr_atomic_cas32(&have_init_ssl, INIT_BUSY, INIT_UNINITIALIZED); if (!val) { -#if APR_HAS_THREADS +#if APR_HAS_THREADS && defined(USE_LEGACY_OPENSSL) int i, numlocks; #endif @@ -1330,13 +1416,17 @@ } #endif +#ifndef USE_LEGACY_OPENSSL + OPENSSL_malloc_init(); +#else CRYPTO_malloc_init(); +#endif ERR_load_crypto_strings(); SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); -#if APR_HAS_THREADS +#if APR_HAS_THREADS && defined(USE_LEGACY_OPENSSL) numlocks = CRYPTO_num_locks(); apr_pool_create(&ssl_pool, NULL); ssl_locks = apr_palloc(ssl_pool, sizeof(apr_thread_mutex_t*)*numlocks); @@ -1392,6 +1482,7 @@ const char *cert_path; apr_file_t *cert_file; BIO *bio; + BIO_METHOD *biom; PKCS12 *p12; int i; int retrying_success = 0; @@ -1418,8 +1509,9 @@ continue; } - bio = BIO_new(&bio_file_method); - bio->ptr = cert_file; + biom = bio_meth_file_new(); + bio = BIO_new(biom); + bio_set_data(bio, cert_file); ctx->cert_path = cert_path; p12 = d2i_PKCS12_bio(bio, NULL); @@ -1430,6 +1522,7 @@ if (i == 1) { PKCS12_free(p12); + bio_meth_free(biom); ctx->cached_cert = *cert; ctx->cached_cert_pw = *pkey; if (!retrying_success && ctx->cert_cache_pool) { @@ -1465,6 +1558,7 @@ i = PKCS12_parse(p12, password, pkey, cert, NULL); if (i == 1) { PKCS12_free(p12); + bio_meth_free(biom); ctx->cached_cert = *cert; ctx->cached_cert_pw = *pkey; if (!retrying_success && ctx->cert_cache_pool) { @@ -1492,6 +1586,7 @@ } } PKCS12_free(p12); + bio_meth_free(biom); return 0; } else { @@ -1500,6 +1595,7 @@ ERR_GET_FUNC(err), ERR_GET_REASON(err)); PKCS12_free(p12); + bio_meth_free(biom); } } } @@ -1630,8 +1726,9 @@ disable_compression(ssl_ctx); ssl_ctx->ssl = SSL_new(ssl_ctx->ctx); - ssl_ctx->bio = BIO_new(&bio_bucket_method); - ssl_ctx->bio->ptr = ssl_ctx; + ssl_ctx->biom = bio_meth_bucket_new(); + ssl_ctx->bio = BIO_new(ssl_ctx->biom); + bio_set_data(ssl_ctx->bio, ssl_ctx); SSL_set_bio(ssl_ctx->ssl, ssl_ctx->bio, ssl_ctx->bio); @@ -1677,6 +1774,7 @@ /* SSL_free implicitly frees the underlying BIO. */ SSL_free(ssl_ctx->ssl); SSL_CTX_free(ssl_ctx->ctx); + bio_meth_free(ssl_ctx->biom); serf_bucket_mem_free(ssl_ctx->allocator, ssl_ctx); @@ -1822,6 +1920,7 @@ apr_file_t *cert_file; apr_status_t status; BIO *bio; + BIO_METHOD *biom; X509 *ssl_cert; /* We use an apr file instead of an stdio.h file to avoid usage problems @@ -1835,13 +1934,15 @@ init_ssl_libraries(); - bio = BIO_new(&bio_file_method); - bio->ptr = cert_file; + biom = bio_meth_file_new(); + bio = BIO_new(biom); + bio_set_data(bio, cert_file); ssl_cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); apr_file_close(cert_file); BIO_free(bio); + bio_meth_free(biom); if (ssl_cert) { /* TODO: Setup pool cleanup to free certificate */ @@ -1880,7 +1981,7 @@ X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK| X509_V_FLAG_CRL_CHECK_ALL); } else { - X509_VERIFY_PARAM_clear_flags(store->param, X509_V_FLAG_CRL_CHECK| + X509_VERIFY_PARAM_clear_flags(X509_STORE_get0_param(store), X509_V_FLAG_CRL_CHECK| X509_V_FLAG_CRL_CHECK_ALL); } return APR_SUCCESS; @@ -1894,6 +1995,7 @@ X509_CRL *crl = NULL; X509_STORE *store; BIO *bio; + BIO_METHOD *biom; int result; apr_status_t status; @@ -1903,13 +2005,15 @@ return status; } - bio = BIO_new(&bio_file_method); - bio->ptr = crl_file; + biom = bio_meth_file_new(); + bio = BIO_new(biom); + bio_set_data(bio, crl_file); crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL); apr_file_close(crl_file); BIO_free(bio); + bio_meth_free(biom); store = SSL_CTX_get_cert_store(ssl_ctx->ctx); Index: trunk/test/MockHTTPinC/MockHTTP_server.c =================================================================== --- trunk/test/MockHTTPinC/MockHTTP_server.c (revision 1748479) +++ trunk/test/MockHTTPinC/MockHTTP_server.c (working copy) @@ -2239,6 +2239,10 @@ #include <openssl/ssl.h> #include <openssl/err.h> +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L +#define USE_LEGACY_OPENSSL +#endif + struct sslCtx_t { bool handshake_done; bool renegotiate; @@ -2247,6 +2251,7 @@ SSL_CTX* ctx; SSL* ssl; BIO *bio; + BIO_METHOD *biom; char read_buffer[8192]; }; @@ -2273,14 +2278,38 @@ */ static int bio_apr_socket_create(BIO *bio) { +#ifndef USE_LEGACY_OPENSSL + BIO_set_shutdown(bio, 1); + BIO_set_init(bio, 1); + BIO_set_data(bio, NULL); +#else bio->shutdown = 1; bio->init = 1; bio->num = -1; bio->ptr = NULL; +#endif return 1; } +static void bio_set_data(BIO *bio, void *data) +{ +#ifndef USE_LEGACY_OPENSSL + BIO_set_data(bio, data); +#else + bio->ptr = data; +#endif +} + +static void *bio_get_data(BIO *bio) +{ +#ifndef USE_LEGACY_OPENSSL + return BIO_get_data(bio); +#else + return bio->ptr; +#endif +} + /** * OpenSSL BIO callback. Cleans up the BIO structure. */ @@ -2322,7 +2351,7 @@ static int bio_apr_socket_read(BIO *bio, char *in, int inlen) { apr_size_t len = inlen; - _mhClientCtx_t *cctx = bio->ptr; + _mhClientCtx_t *cctx = bio_get_data(bio); sslCtx_t *ssl_ctx = cctx->ssl_ctx; apr_status_t status; @@ -2351,7 +2380,7 @@ static int bio_apr_socket_write(BIO *bio, const char *in, int inlen) { apr_size_t len = inlen; - _mhClientCtx_t *cctx = bio->ptr; + _mhClientCtx_t *cctx = bio_get_data(bio); sslCtx_t *ssl_ctx = cctx->ssl_ctx; apr_status_t status; @@ -2375,6 +2404,7 @@ } +#ifdef USE_LEGACY_OPENSSL static BIO_METHOD bio_apr_socket_method = { BIO_TYPE_SOCKET, "APR sockets", @@ -2389,7 +2419,35 @@ NULL /* sslc does not have the callback_ctrl field */ #endif }; +#endif +static BIO_METHOD *bio_meth_apr_socket_new(void) +{ + BIO_METHOD *biom = NULL; + +#ifndef USE_LEGACY_OPENSSL + biom = BIO_meth_new(BIO_TYPE_SOCKET, "APR sockets"); + if (biom) { + BIO_meth_set_write(biom, bio_apr_socket_write); + BIO_meth_set_read(biom, bio_apr_socket_read); + BIO_meth_set_ctrl(biom, bio_apr_socket_ctrl); + BIO_meth_set_create(biom, bio_apr_socket_create); + BIO_meth_set_destroy(biom, bio_apr_socket_destroy); + } +#else + biom = &bio_apr_socket_method; +#endif + + return biom; +} + +static void bio_meth_free(BIO_METHOD *biom) +{ +#ifndef USE_LEGACY_OPENSSL + BIO_meth_free(biom); +#endif +} + static int ocspCreateResponse(OCSP_RESPONSE **resp, mhOCSPRespnseStatus_t status) { int ret = 1; @@ -2527,8 +2585,10 @@ sslCtx_t *ssl_ctx = cctx->ssl_ctx; if (ssl_ctx) { - if (ssl_ctx->ssl) + if (ssl_ctx->ssl) { SSL_clear(ssl_ctx->ssl); + bio_meth_free(ssl_ctx->biom); + } SSL_CTX_free(ssl_ctx->ctx); } @@ -2608,7 +2668,11 @@ /* Init OpenSSL globally */ if (!init_done) { +#ifndef USE_LEGACY_OPENSSL + OPENSSL_malloc_init(); +#else CRYPTO_malloc_init(); +#endif ERR_load_crypto_strings(); SSL_load_error_strings(); SSL_library_init(); @@ -2720,8 +2784,8 @@ | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); - ssl_ctx->bio = BIO_new(&bio_apr_socket_method); - ssl_ctx->bio->ptr = cctx; + ssl_ctx->bio = BIO_new(bio_meth_apr_socket_new()); + bio_set_data(ssl_ctx->bio, cctx); initSSL(cctx); apr_pool_cleanup_register(cctx->pool, cctx,