Based on serf changes: #From 03f3f8a6d56726bed26eb3202dfb1e485274ca90 Mon Sep 17 00:00:00 2001 #From: Bert Huijben #Date: Thu, 16 Jun 2016 09:47:56 +0000 #Subject: [PATCH] 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' # #* 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 #--- # buckets/ssl_buckets.c | 146 ++++++++++++++++++++++++----- # test/MockHTTPinC/MockHTTP_server.c | 74 ++++++++++++++- # 2 files changed, 194 insertions(+), 26 deletions(-) --- modpagespeed-1.9.32.4/third_party/serf/instaweb_ssl_buckets.c.orig 2015-07-14 01:16:54.000000000 +0200 +++ modpagespeed-1.9.32.4/third_party/serf/instaweb_ssl_buckets.c 2019-04-17 06:45:35.833070953 +0200 @@ -68,6 +68,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 + /*#define SSL_VERBOSE*/ @@ -158,6 +163,7 @@ SSL_CTX *ctx; SSL *ssl; BIO *bio; + BIO_METHOD *biom; serf_ssl_stream_t encrypt; serf_ssl_stream_t decrypt; @@ -203,10 +209,28 @@ int depth; }; +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; @@ -252,7 +276,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; #ifdef SSL_VERBOSE @@ -281,7 +305,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; @@ -306,7 +330,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); @@ -324,10 +348,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; } @@ -364,6 +394,7 @@ return ret; } +#ifdef USE_LEGACY_OPENSSL static BIO_METHOD bio_bucket_method = { BIO_TYPE_MEM, "Serf SSL encryption and decryption buckets", @@ -393,6 +424,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 +} static int validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx) @@ -799,7 +880,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; @@ -878,18 +959,22 @@ #endif if (!val) { -#if APR_HAS_THREADS +#if APR_HAS_THREADS && defined(USE_LEGACY_OPENSSL) int i, numlocks; #endif #ifndef OPENSSL_IS_BORINGSSL +#ifndef USE_LEGACY_OPENSSL + OPENSSL_malloc_init(); +#else CRYPTO_malloc_init(); #endif +#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); @@ -929,6 +1014,7 @@ const char *cert_path; apr_file_t *cert_file; BIO *bio; + BIO_METHOD *biom; PKCS12 *p12; int i; int retrying_success = 0; @@ -954,8 +1040,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); @@ -965,6 +1052,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) { @@ -1005,6 +1093,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) { @@ -1032,6 +1121,7 @@ } } PKCS12_free(p12); + bio_meth_free(biom); return 0; } else { @@ -1039,6 +1129,7 @@ ERR_GET_FUNC(err), ERR_GET_REASON(err)); PKCS12_free(p12); + bio_meth_free(biom); } } } @@ -1135,8 +1226,9 @@ SSL_CTX_set_options(ssl_ctx->ctx, SSL_OP_ALL); 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); @@ -1180,6 +1272,7 @@ ssl_ctx->ssl = NULL; SSL_CTX_free(ssl_ctx->ctx); ssl_ctx->ctx = NULL; + bio_meth_free(ssl_ctx->biom); p = ssl_ctx->pool;