Adapt to OpenSSL 1.1.x API changes.

OpenSSL 1.1.x makes various types opaque, requiring the use of
accessors, and rewrote the state machine describing the handshake
process.  Of particular interest to serf are the BIO, BIO_METHOD, and
X509_STORE types.

Patch by: 'James McCoy' <jamessan{_AT_}debian.org>

* buckets/ssl_buckets.c
  (): New USE_LEGACY_OPENSSL define
  (): New X509_STORE_get0_param() define for use with pre-1.1.x OpenSSL
  (detect_renegotiate): Use SSL_get_state to check for the
    TLS_ST_SW_HELLO_REQ state, indicating the server is starting a new
    negotiation.
  (bio_set_data, bio_get_data): New functions to abstract access to
    the BIO data.
  (bio_bucket_read, bio_bucket_write, bio_file_read, bio_file_write,
   bio_file_gets): Use bio_get_data.
  (bio_bucket_create): Use BIO accessor functions when available.
  (bio_meth_bucket_new, bio_meth_file_new): New functions to abstract
    creation of BIO_METHOD.  With OpenSSL 1.1.x or newer, the BIO_meth_*
    functions are used to allocate a new BIO_METOD and set the
    callbacks, otherwise the pointers to the statically defined structs
    are used.
  (bio_meth_free): New function.
  (ocsp_callback): Use OCSP_response_status to get status instead of
    accessing internals of OCSP_RESPONSE struct.  Remove unused
    OCSP_RESPBYTES variable.
  (ssl_decrypt): Use SSL_get_state to check for the TLS_ST_OK state,
    indicating completed handshake.
  (init_ssl_libraries): Exclude threading code when OpenSSL 1.1.x is in
    use since OpenSSL now handles this appropriately without users of
    the library setting up locking functions.
  (ssl_need_client_cert, ssl_init_context, serf_ssl_load_cert_file,
   serf_ssl_add_crl_from_file): Use new bio_meth_*_new functions to
   provide the BIO_METHOD* to BIO_new().  Also use the bio_set_data
   function to set the data for the callback.

* test/MockHTTPinC/MockHTTP_server.c
  (): New USE_OPENSSL_1_1_API define
  (bio_set_data, bio_get_data): New functions to abstract access to
    the BIO data.
  (bio_apr_socket_read, bio_apr_socket_write): Use bio_get_data.
  (bio_apr_socket_create): Use BIO accessor functions when available.
  (bio_meth_apr_socket_new): New function to abstract creation of
    BIO_METHOD.  With OpenSSL 1.1.x or newer, the BIO_meth_* functions
    are used to allocate a new BIO_METOD and set the callbacks,
    otherwise the pointer to the statically defined struct is used.
  (initSSLCtx): Use new bio_meth_apr_socket_new function to
   provide the BIO_METHOD* to BIO_new().  Also use the bio_set_data
   function to set the data for the callback.


git-svn-id: https://svn.apache.org/repos/asf/serf/trunk@1748673 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/buckets/ssl_buckets.c b/buckets/ssl_buckets.c
index 8357a49..7a8cf93 100644
--- a/buckets/ssl_buckets.c
+++ b/buckets/ssl_buckets.c
@@ -49,6 +49,11 @@
 #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,6 +536,56 @@
     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.
@@ -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);
 
diff --git a/test/MockHTTPinC/MockHTTP_server.c b/test/MockHTTPinC/MockHTTP_server.c
index df253f8..92fe124 100644
--- a/test/MockHTTPinC/MockHTTP_server.c
+++ b/test/MockHTTPinC/MockHTTP_server.c
@@ -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,6 +2419,34 @@
     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)
 {
@@ -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,