diff --git a/kmipclient/CMakeLists.txt b/kmipclient/CMakeLists.txt index d4d96be..7ecf46f 100644 --- a/kmipclient/CMakeLists.txt +++ b/kmipclient/CMakeLists.txt @@ -5,6 +5,7 @@ project(kmipclient) set(CMAKE_CXX_STANDARD 20) find_package(OpenSSL REQUIRED) +find_package(Threads REQUIRED) add_library( kmipclient @@ -43,7 +44,7 @@ target_include_directories( $ ) -target_link_libraries(kmipclient PUBLIC kmipcore OpenSSL::SSL OpenSSL::Crypto) +target_link_libraries(kmipclient PUBLIC kmipcore OpenSSL::SSL OpenSSL::Crypto Threads::Threads) set_property(TARGET kmipclient PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/kmipclient/src/NetClientOpenSSL.cpp b/kmipclient/src/NetClientOpenSSL.cpp index 3d41af2..75cdabc 100644 --- a/kmipclient/src/NetClientOpenSSL.cpp +++ b/kmipclient/src/NetClientOpenSSL.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,28 @@ namespace kmipclient { return inet_pton(AF_INET6, host.c_str(), &addr6) == 1; } + // TLS_method() was introduced in OpenSSL 1.1.0. + // Older builds (OpenSSL < 1.1.0) use the SSLv23_method() alias. + static const SSL_METHOD *get_tls_client_method() { +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + return SSLv23_method(); +#else + return TLS_method(); +#endif + } + + // SSL_get0_peer_certificate() (borrowed ref, no X509_free needed) was + // introduced in OpenSSL 3.0. OpenSSL 1.0.x and 1.1.x — including the + // OpenSSL 1.1.1 shipped with Oracle Linux 8 — only have + // SSL_get_peer_certificate() which bumps the refcount and requires X509_free. + static X509 *get_peer_certificate(SSL *ssl) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) + return SSL_get0_peer_certificate(ssl); +#else + return SSL_get_peer_certificate(ssl); +#endif + } + static void configure_tls_verification( SSL_CTX *ctx, SSL *ssl, @@ -141,13 +164,19 @@ namespace kmipclient { return; } - if (SSL_get0_peer_certificate(ssl) == nullptr) { + X509 *peer_cert = get_peer_certificate(ssl); + if (peer_cert == nullptr) { throw KmipIOException( kmipcore::KMIP_IO_FAILURE, "TLS peer verification failed: server did not present a certificate" ); } +#if OPENSSL_VERSION_NUMBER < 0x30000000L || defined(LIBRESSL_VERSION_NUMBER) + // SSL_get_peer_certificate() bumps the refcount; release the reference. + X509_free(peer_cert); +#endif + const long verify_result = SSL_get_verify_result(ssl); if (verify_result != X509_V_OK) { throw KmipIOException( @@ -328,7 +357,9 @@ namespace kmipclient { ctx_.reset(); } - std::unique_ptr new_ctx(SSL_CTX_new(TLS_method())); + std::unique_ptr new_ctx( + SSL_CTX_new(get_tls_client_method()) + ); if (!new_ctx) { throw KmipIOException( kmipcore::KMIP_IO_FAILURE, diff --git a/kmipcore/include/kmipcore/kmipcore_version.hpp b/kmipcore/include/kmipcore/kmipcore_version.hpp index 54b3a6a..78f5ba9 100644 --- a/kmipcore/include/kmipcore/kmipcore_version.hpp +++ b/kmipcore/include/kmipcore/kmipcore_version.hpp @@ -23,7 +23,7 @@ /** @brief kmipcore semantic version minor component. */ #define KMIPCORE_VERSION_MINOR 1 /** @brief kmipcore semantic version patch component. */ -#define KMIPCORE_VERSION_PATCH 1 +#define KMIPCORE_VERSION_PATCH 2 /** @brief Internal helper for macro stringification. */ #define KMIPCORE_STRINGIFY_I(x) #x