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,

Reply via email to