src: Compile with OpenSSL 1.1.0-pre5

* don't use CRYPTO_LOCK stuff (they are sorted out by openssl, and no
  application intervention is required, just like boringSSL)
* don't use OPENSSL_config
* use provided API to access BIO member
This commit is contained in:
Tatsuhiro Tsujikawa 2016-05-07 16:18:58 +09:00
parent 15a9dfbaea
commit 6d22898936
8 changed files with 123 additions and 15 deletions

View File

@ -226,6 +226,7 @@ lib_LTLIBRARIES = libnghttp2_asio.la
libnghttp2_asio_la_SOURCES = \ libnghttp2_asio_la_SOURCES = \
util.cc util.h http2.cc http2.h \ util.cc util.h http2.cc http2.h \
ssl.cc ssl.h \ ssl.cc ssl.h \
ssl_compat.h \
timegm.c timegm.h \ timegm.c timegm.h \
asio_common.cc asio_common.h \ asio_common.cc asio_common.h \
asio_io_service_pool.cc asio_io_service_pool.h \ asio_io_service_pool.cc asio_io_service_pool.h \

View File

@ -81,6 +81,7 @@
#include "shrpx_worker_process.h" #include "shrpx_worker_process.h"
#include "shrpx_process.h" #include "shrpx_process.h"
#include "shrpx_signal.h" #include "shrpx_signal.h"
#include "shrpx_connection.h"
#include "util.h" #include "util.h"
#include "app_helper.h" #include "app_helper.h"
#include "ssl.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.alpn_prefs = ssl::set_alpn_prefs(tlsconf.npn_list);
tlsconf.bio_method = create_bio_method();
auto &listenerconf = mod_config()->conn.listener; auto &listenerconf = mod_config()->conn.listener;
auto &upstreamconf = mod_config()->conn.upstream; auto &upstreamconf = mod_config()->conn.upstream;
auto &downstreamconf = mod_config()->conn.downstream; auto &downstreamconf = mod_config()->conn.downstream;

View File

@ -463,6 +463,7 @@ struct TLSConfig {
std::vector<std::string> npn_list; std::vector<std::string> npn_list;
// list of supported SSL/TLS protocol strings. // list of supported SSL/TLS protocol strings.
std::vector<std::string> tls_proto_list; std::vector<std::string> tls_proto_list;
BIO_METHOD *bio_method;
// Bit mask to disable SSL/TLS protocol versions. This will be // Bit mask to disable SSL/TLS protocol versions. This will be
// passed to SSL_CTX_set_options(). // passed to SSL_CTX_set_options().
long int tls_proto_mask; long int tls_proto_mask;

View File

@ -36,10 +36,20 @@
#include "shrpx_memcached_request.h" #include "shrpx_memcached_request.h"
#include "memchunk.h" #include "memchunk.h"
#include "util.h" #include "util.h"
#include "ssl_compat.h"
using namespace nghttp2; using namespace nghttp2;
namespace shrpx { 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, Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl,
MemchunkPool *mcpool, ev_tstamp write_timeout, MemchunkPool *mcpool, ev_tstamp write_timeout,
ev_tstamp read_timeout, ev_tstamp read_timeout,
@ -140,7 +150,7 @@ int shrpx_bio_write(BIO *b, const char *buf, int len) {
return 0; return 0;
} }
auto conn = static_cast<Connection *>(b->ptr); auto conn = static_cast<Connection *>(BIO_get_data(b));
auto &wbuf = conn->tls.wbuf; auto &wbuf = conn->tls.wbuf;
BIO_clear_retry_flags(b); BIO_clear_retry_flags(b);
@ -181,7 +191,7 @@ int shrpx_bio_read(BIO *b, char *buf, int len) {
return 0; return 0;
} }
auto conn = static_cast<Connection *>(b->ptr); auto conn = static_cast<Connection *>(BIO_get_data(b));
auto &rbuf = conn->tls.rbuf; auto &rbuf = conn->tls.rbuf;
BIO_clear_retry_flags(b); BIO_clear_retry_flags(b);
@ -230,10 +240,14 @@ long shrpx_bio_ctrl(BIO *b, int cmd, long num, void *ptr) {
namespace { namespace {
int shrpx_bio_create(BIO *b) { int shrpx_bio_create(BIO *b) {
#if OPENSSL_101_API
BIO_set_init(b, 1);
#else // !OPENSSL_101_API
b->init = 1; b->init = 1;
b->num = 0; b->num = 0;
b->ptr = nullptr; b->ptr = nullptr;
b->flags = 0; b->flags = 0;
#endif // !OPENSSL_101_API
return 1; return 1;
} }
} // namespace } // namespace
@ -244,26 +258,55 @@ int shrpx_bio_destroy(BIO *b) {
return 0; return 0;
} }
#if !OPENSSL_101_API
b->ptr = nullptr; b->ptr = nullptr;
b->init = 0; b->init = 0;
b->flags = 0; b->flags = 0;
#endif // !OPENSSL_101_API
return 1; return 1;
} }
} // namespace } // namespace
namespace { #if OPENSSL_101_API
BIO_METHOD shrpx_bio_method = {
BIO_TYPE_FD, "nghttpx-bio", shrpx_bio_write, BIO_METHOD *create_bio_method() {
shrpx_bio_read, shrpx_bio_puts, shrpx_bio_gets, auto meth = BIO_meth_new(BIO_TYPE_FD, "nghttpx-bio");
shrpx_bio_ctrl, shrpx_bio_create, shrpx_bio_destroy, BIO_meth_set_write(meth, shrpx_bio_write);
}; BIO_meth_set_read(meth, shrpx_bio_read);
} // namespace 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) { void Connection::set_ssl(SSL *ssl) {
tls.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_bio(tls.ssl, bio, bio);
SSL_set_app_data(tls.ssl, this); SSL_set_app_data(tls.ssl, this);
} }

View File

@ -139,6 +139,15 @@ struct Connection {
shrpx_proto proto; 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 } // namespace shrpx
#endif // SHRPX_CONNECTION_H #endif // SHRPX_CONNECTION_H

View File

@ -61,6 +61,7 @@
#include "util.h" #include "util.h"
#include "ssl.h" #include "ssl.h"
#include "template.h" #include "template.h"
#include "ssl_compat.h"
using namespace nghttp2; using namespace nghttp2;
@ -243,8 +244,13 @@ int tls_session_new_cb(SSL *ssl, SSL_SESSION *session) {
} // namespace } // namespace
namespace { namespace {
SSL_SESSION *tls_session_get_cb(SSL *ssl, unsigned char *id, int idlen, SSL_SESSION *tls_session_get_cb(SSL *ssl,
int *copy) { #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<Connection *>(SSL_get_app_data(ssl)); auto conn = static_cast<Connection *>(SSL_get_app_data(ssl));
auto handler = static_cast<ClientHandler *>(conn->data); auto handler = static_cast<ClientHandler *>(conn->data);
auto worker = handler->get_worker(); auto worker = handler->get_worker();

View File

@ -32,6 +32,8 @@
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/conf.h> #include <openssl/conf.h>
#include "ssl_compat.h"
namespace nghttp2 { namespace nghttp2 {
namespace ssl { namespace ssl {
@ -52,6 +54,14 @@ const char *const DEFAULT_CIPHER_LIST =
"SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-" "SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-"
"SHA:DES-CBC3-SHA:!DSS"; "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 { namespace {
std::vector<std::mutex> ssl_global_locks; std::vector<std::mutex> ssl_global_locks;
} // namespace } // namespace
@ -81,6 +91,8 @@ LibsslGlobalLock::LibsslGlobalLock() {
LibsslGlobalLock::~LibsslGlobalLock() { ssl_global_locks.clear(); } LibsslGlobalLock::~LibsslGlobalLock() { ssl_global_locks.clear(); }
#endif // !OPENSSL_101_API
const char *get_tls_protocol(SSL *ssl) { const char *get_tls_protocol(SSL *ssl) {
switch (SSL_version(ssl)) { switch (SSL_version(ssl)) {
case SSL2_VERSION: case SSL2_VERSION:
@ -152,9 +164,12 @@ bool check_http2_requirement(SSL *ssl) {
} }
void libssl_init() { 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); OPENSSL_config(nullptr);
#endif // OPENSSL_IS_BORINGSSL #endif // !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_101_API
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();

30
src/ssl_compat.h Normal file
View File

@ -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