diff --git a/src/Makefile.am b/src/Makefile.am index 7f1cabe7..01701838 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -226,6 +226,7 @@ lib_LTLIBRARIES = libnghttp2_asio.la libnghttp2_asio_la_SOURCES = \ util.cc util.h http2.cc http2.h \ ssl.cc ssl.h \ + ssl_compat.h \ timegm.c timegm.h \ asio_common.cc asio_common.h \ asio_io_service_pool.cc asio_io_service_pool.h \ diff --git a/src/shrpx.cc b/src/shrpx.cc index cd655f8c..0534d739 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -81,6 +81,7 @@ #include "shrpx_worker_process.h" #include "shrpx_process.h" #include "shrpx_signal.h" +#include "shrpx_connection.h" #include "util.h" #include "app_helper.h" #include "ssl.h" @@ -2073,6 +2074,8 @@ void process_options(int argc, char **argv, tlsconf.alpn_prefs = ssl::set_alpn_prefs(tlsconf.npn_list); + tlsconf.bio_method = create_bio_method(); + auto &listenerconf = mod_config()->conn.listener; auto &upstreamconf = mod_config()->conn.upstream; auto &downstreamconf = mod_config()->conn.downstream; diff --git a/src/shrpx_config.h b/src/shrpx_config.h index 09471d21..f801a0ea 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -463,6 +463,7 @@ struct TLSConfig { std::vector npn_list; // list of supported SSL/TLS protocol strings. std::vector tls_proto_list; + BIO_METHOD *bio_method; // Bit mask to disable SSL/TLS protocol versions. This will be // passed to SSL_CTX_set_options(). long int tls_proto_mask; diff --git a/src/shrpx_connection.cc b/src/shrpx_connection.cc index 428d98c4..95e1c320 100644 --- a/src/shrpx_connection.cc +++ b/src/shrpx_connection.cc @@ -36,10 +36,20 @@ #include "shrpx_memcached_request.h" #include "memchunk.h" #include "util.h" +#include "ssl_compat.h" using namespace nghttp2; namespace shrpx { + +#if !OPENSSL_101_API + +void *BIO_get_data(BIO *bio) { return bio->ptr; } +void BIO_set_data(BIO *bio, void *ptr) { bio->ptr = ptr; } +void BIO_set_init(BIO *bio, int init) { bio->init = init; } + +#endif // !OPENSSL_101_API + Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl, MemchunkPool *mcpool, ev_tstamp write_timeout, ev_tstamp read_timeout, @@ -140,7 +150,7 @@ int shrpx_bio_write(BIO *b, const char *buf, int len) { return 0; } - auto conn = static_cast(b->ptr); + auto conn = static_cast(BIO_get_data(b)); auto &wbuf = conn->tls.wbuf; BIO_clear_retry_flags(b); @@ -181,7 +191,7 @@ int shrpx_bio_read(BIO *b, char *buf, int len) { return 0; } - auto conn = static_cast(b->ptr); + auto conn = static_cast(BIO_get_data(b)); auto &rbuf = conn->tls.rbuf; BIO_clear_retry_flags(b); @@ -230,10 +240,14 @@ long shrpx_bio_ctrl(BIO *b, int cmd, long num, void *ptr) { namespace { int shrpx_bio_create(BIO *b) { +#if OPENSSL_101_API + BIO_set_init(b, 1); +#else // !OPENSSL_101_API b->init = 1; b->num = 0; b->ptr = nullptr; b->flags = 0; +#endif // !OPENSSL_101_API return 1; } } // namespace @@ -244,26 +258,55 @@ int shrpx_bio_destroy(BIO *b) { return 0; } +#if !OPENSSL_101_API b->ptr = nullptr; b->init = 0; b->flags = 0; +#endif // !OPENSSL_101_API return 1; } } // namespace -namespace { -BIO_METHOD shrpx_bio_method = { - BIO_TYPE_FD, "nghttpx-bio", shrpx_bio_write, - shrpx_bio_read, shrpx_bio_puts, shrpx_bio_gets, - shrpx_bio_ctrl, shrpx_bio_create, shrpx_bio_destroy, -}; -} // namespace +#if OPENSSL_101_API + +BIO_METHOD *create_bio_method() { + auto meth = BIO_meth_new(BIO_TYPE_FD, "nghttpx-bio"); + BIO_meth_set_write(meth, shrpx_bio_write); + BIO_meth_set_read(meth, shrpx_bio_read); + BIO_meth_set_puts(meth, shrpx_bio_puts); + BIO_meth_set_gets(meth, shrpx_bio_gets); + BIO_meth_set_ctrl(meth, shrpx_bio_ctrl); + BIO_meth_set_create(meth, shrpx_bio_create); + BIO_meth_set_destroy(meth, shrpx_bio_destroy); + + return meth; +} + +void delete_bio_method(BIO_METHOD *bio_method) { BIO_meth_free(bio_method); } + +#else // !OPENSSL_101_API + +BIO_METHOD *create_bio_method() { + static BIO_METHOD shrpx_bio_method = { + BIO_TYPE_FD, "nghttpx-bio", shrpx_bio_write, + shrpx_bio_read, shrpx_bio_puts, shrpx_bio_gets, + shrpx_bio_ctrl, shrpx_bio_create, shrpx_bio_destroy, + }; + + return &shrpx_bio_method; +} + +void delete_bio_method(BIO_METHOD *bio_method) {} + +#endif // !OPENSSL_101_API void Connection::set_ssl(SSL *ssl) { tls.ssl = ssl; - auto bio = BIO_new(&shrpx_bio_method); - bio->ptr = this; + + auto &tlsconf = get_config()->tls; + auto bio = BIO_new(tlsconf.bio_method); + BIO_set_data(bio, this); SSL_set_bio(tls.ssl, bio, bio); SSL_set_app_data(tls.ssl, this); } diff --git a/src/shrpx_connection.h b/src/shrpx_connection.h index 71ba33f4..a361e15e 100644 --- a/src/shrpx_connection.h +++ b/src/shrpx_connection.h @@ -139,6 +139,15 @@ struct Connection { shrpx_proto proto; }; +// Creates BIO_method shared by all SSL objects. If nghttp2 is built +// with OpenSSL < 1.1.0, this returns statically allocated object. +// Otherwise, it returns new BIO_METHOD object every time. +BIO_METHOD *create_bio_method(); + +// Deletes given |bio_method|. If nghttp2 is built with OpenSSL < +// 1.1.0, this function is noop. +void delete_bio_method(BIO_METHOD *bio_method); + } // namespace shrpx #endif // SHRPX_CONNECTION_H diff --git a/src/shrpx_ssl.cc b/src/shrpx_ssl.cc index 5feac51d..f500d446 100644 --- a/src/shrpx_ssl.cc +++ b/src/shrpx_ssl.cc @@ -61,6 +61,7 @@ #include "util.h" #include "ssl.h" #include "template.h" +#include "ssl_compat.h" using namespace nghttp2; @@ -243,8 +244,13 @@ int tls_session_new_cb(SSL *ssl, SSL_SESSION *session) { } // namespace namespace { -SSL_SESSION *tls_session_get_cb(SSL *ssl, unsigned char *id, int idlen, - int *copy) { +SSL_SESSION *tls_session_get_cb(SSL *ssl, +#if OPENSSL_101_API + const unsigned char *id, +#else // !OPENSSL_101_API + unsigned char *id, +#endif // !OPENSSL_101_API + int idlen, int *copy) { auto conn = static_cast(SSL_get_app_data(ssl)); auto handler = static_cast(conn->data); auto worker = handler->get_worker(); diff --git a/src/ssl.cc b/src/ssl.cc index 8d8cd782..0dc34ff7 100644 --- a/src/ssl.cc +++ b/src/ssl.cc @@ -32,6 +32,8 @@ #include #include +#include "ssl_compat.h" + namespace nghttp2 { namespace ssl { @@ -52,6 +54,14 @@ const char *const DEFAULT_CIPHER_LIST = "SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-" "SHA:DES-CBC3-SHA:!DSS"; +#if OPENSSL_101_API + +// CRYPTO_LOCK is deprecated as of OpenSSL 1.1.0 +LibsslGlobalLock::LibsslGlobalLock() {} +LibsslGlobalLock::~LibsslGlobalLock() {} + +#else // !OPENSSL_101_API + namespace { std::vector ssl_global_locks; } // namespace @@ -81,6 +91,8 @@ LibsslGlobalLock::LibsslGlobalLock() { LibsslGlobalLock::~LibsslGlobalLock() { ssl_global_locks.clear(); } +#endif // !OPENSSL_101_API + const char *get_tls_protocol(SSL *ssl) { switch (SSL_version(ssl)) { case SSL2_VERSION: @@ -152,9 +164,12 @@ bool check_http2_requirement(SSL *ssl) { } void libssl_init() { -#ifndef OPENSSL_IS_BORINGSSL +// OPENSSL_config() is not available in BoringSSL. It is also +// deprecated as of OpenSSL 1.1.0. +#if !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_101_API OPENSSL_config(nullptr); -#endif // OPENSSL_IS_BORINGSSL +#endif // !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_101_API + SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); diff --git a/src/ssl_compat.h b/src/ssl_compat.h new file mode 100644 index 00000000..4b015624 --- /dev/null +++ b/src/ssl_compat.h @@ -0,0 +1,30 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2016 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef OPENSSL_COMPAT_H + +#define OPENSSL_101_API \ + (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100005L) + +#endif // OPENSSL_COMPAT_H