mirror of
https://github.com/arvidn/libtorrent.git
synced 2026-05-06 07:56:47 -04:00
Imported GnuTLS wrapper and added SSL generic functions
Co-authored-by: Paul-Louis Ageneau <paul-louis@ageneau.org>
This commit is contained in:
committed by
Arvid Norberg
parent
90abe788f1
commit
f8ac0ba98c
@@ -4,3 +4,6 @@
|
||||
[submodule "deps/try_signal"]
|
||||
path = deps/try_signal
|
||||
url = https://github.com/arvidn/try_signal.git
|
||||
[submodule "deps/asio-gnutls"]
|
||||
path = deps/asio-gnutls
|
||||
url = https://github.com/paullouisageneau/boost-asio-gnutls.git
|
||||
|
||||
@@ -713,6 +713,7 @@ endif()
|
||||
# Boost
|
||||
find_public_dependency(Boost REQUIRED COMPONENTS system)
|
||||
target_include_directories(torrent-rasterbar PUBLIC ${Boost_INCLUDE_DIRS})
|
||||
target_include_directories(torrent-rasterbar PUBLIC deps/asio-gnutls/include)
|
||||
target_link_libraries(torrent-rasterbar PUBLIC ${Boost_SYSTEM_LIBRARY})
|
||||
|
||||
if (exceptions)
|
||||
|
||||
+1
Submodule deps/asio-gnutls added at 4c7ca91361
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018, Alexandre Janniaux
|
||||
Copyright (c) 2020, Paul-Louis Ageneau
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_SSL_HPP_INCLUDED
|
||||
#define TORRENT_SSL_HPP_INCLUDED
|
||||
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/string_view.hpp"
|
||||
#include "libtorrent/aux_/export.hpp"
|
||||
|
||||
#if TORRENT_USE_SSL
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#include <boost/system/system_error.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include <openssl/opensslv.h> // for OPENSSL_VERSION_NUMBER
|
||||
#if OPENSSL_VERSION_NUMBER < 0x1000000fL
|
||||
#error OpenSSL too old, use a recent version with SNI support
|
||||
#endif
|
||||
#ifdef TORRENT_WINDOWS
|
||||
// because openssl includes winsock.h, we must include winsock2.h first
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_USE_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <boost/asio/gnutls.hpp>
|
||||
#endif
|
||||
|
||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
||||
|
||||
#ifdef TORRENT_BUILD_SIMULATOR
|
||||
#include "simulator/simulator.hpp"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <exception>
|
||||
|
||||
namespace libtorrent {
|
||||
namespace ssl {
|
||||
|
||||
using error_code = boost::system::error_code;
|
||||
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
#if defined TORRENT_BUILD_SIMULATOR
|
||||
using sim::asio::ssl::context;
|
||||
using sim::asio::ssl::stream_base;
|
||||
using sim::asio::ssl::stream;
|
||||
#else
|
||||
using boost::asio::ssl::context;
|
||||
using boost::asio::ssl::stream_base;
|
||||
using boost::asio::ssl::stream;
|
||||
#endif
|
||||
using boost::asio::ssl::verify_context;
|
||||
using boost::asio::ssl::rfc2818_verification;
|
||||
|
||||
using native_context_type = SSL_CTX*;
|
||||
using native_stream_type = SSL*;
|
||||
using context_handle_type = native_context_type;
|
||||
using stream_handle_type = native_stream_type;
|
||||
|
||||
typedef int (*server_name_callback_type)(SSL* s, int*, void* arg);
|
||||
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
using boost::asio::gnutls::context;
|
||||
using boost::asio::gnutls::stream_base;
|
||||
using boost::asio::gnutls::stream;
|
||||
using boost::asio::gnutls::verify_context;
|
||||
using boost::asio::gnutls::rfc2818_verification;
|
||||
|
||||
using native_context_type = context::native_handle_type;
|
||||
using native_stream_type = stream_base::native_handle_type;
|
||||
using context_handle_type = context*;
|
||||
using stream_handle_type = stream_base*;
|
||||
|
||||
typedef bool (*server_name_callback_type)(stream_handle_type handle, std::string const& name, void* arg);
|
||||
|
||||
#endif
|
||||
|
||||
namespace error {
|
||||
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
using boost::asio::error::get_ssl_category;
|
||||
using boost::asio::ssl::error::get_stream_category;
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
using boost::asio::gnutls::error::get_ssl_category;
|
||||
using boost::asio::gnutls::error::get_stream_category;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
inline context_handle_type get_handle(context &c)
|
||||
{
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
return c.native_handle();
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
return &c;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
stream_handle_type get_handle(stream<T>& s)
|
||||
{
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
return s.native_handle();
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
return &s;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
context_handle_type get_context_handle(stream<T>& s)
|
||||
{
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
return SSL_get_SSL_CTX(s.native_handle());
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
return &s.get_context();
|
||||
#endif
|
||||
}
|
||||
|
||||
TORRENT_EXTRA_EXPORT void set_trust_certificate(native_context_type nc, string_view pem, error_code &ec);
|
||||
|
||||
TORRENT_EXTRA_EXPORT void set_server_name_callback(context_handle_type c, server_name_callback_type cb, void* arg, error_code& ec);
|
||||
TORRENT_EXTRA_EXPORT void set_host_name(stream_handle_type s, std::string const& name, error_code& ec);
|
||||
|
||||
TORRENT_EXTRA_EXPORT void set_context(stream_handle_type s, context_handle_type c);
|
||||
TORRENT_EXTRA_EXPORT bool has_context(stream_handle_type s, context_handle_type c);
|
||||
TORRENT_EXTRA_EXPORT context_handle_type get_context(stream_handle_type s);
|
||||
|
||||
} // ssl
|
||||
} // libtorrent
|
||||
|
||||
#endif // TORRENT_USE_SSL
|
||||
|
||||
#endif
|
||||
@@ -34,14 +34,16 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef TORRENT_SSL_STREAM_HPP_INCLUDED
|
||||
#define TORRENT_SSL_STREAM_HPP_INCLUDED
|
||||
|
||||
#include "libtorrent/config.hpp" // for TORRENT_USE_SSL
|
||||
#include "libtorrent/config.hpp"
|
||||
|
||||
#if TORRENT_USE_SSL
|
||||
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/error_code.hpp"
|
||||
#include "libtorrent/io_context.hpp"
|
||||
#include "libtorrent/aux_/openssl.hpp"
|
||||
#include "libtorrent/ssl.hpp"
|
||||
|
||||
#include <boost/system/system_error.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
@@ -61,24 +63,43 @@ struct ssl_stream
|
||||
|
||||
ssl_stream(ssl_stream&&) = default;
|
||||
|
||||
using sock_type = typename boost::asio::ssl::stream<Stream>;
|
||||
using sock_type = typename ssl::stream<Stream>;
|
||||
using next_layer_type = typename sock_type::next_layer_type;
|
||||
using lowest_layer_type = typename Stream::lowest_layer_type;
|
||||
using endpoint_type = typename Stream::endpoint_type;
|
||||
using protocol_type = typename Stream::protocol_type;
|
||||
#if BOOST_VERSION >= 106600
|
||||
using executor_type = typename sock_type::executor_type;
|
||||
executor_type get_executor() { return m_sock->get_executor(); }
|
||||
#endif
|
||||
|
||||
ssl::stream_handle_type handle()
|
||||
{
|
||||
return ssl::get_handle(*m_sock);
|
||||
}
|
||||
|
||||
ssl::context_handle_type context_handle()
|
||||
{
|
||||
return ssl::get_context_handle(*m_sock);
|
||||
}
|
||||
|
||||
void set_host_name(std::string const& name)
|
||||
{
|
||||
aux::openssl_set_tlsext_hostname(m_sock->native_handle(), name.c_str());
|
||||
error_code ec;
|
||||
set_host_name(name, ec);
|
||||
if (ec) boost::throw_exception(boost::system::system_error(ec));
|
||||
}
|
||||
|
||||
void set_host_name(std::string const& name, error_code& ec)
|
||||
{
|
||||
ssl::set_host_name(handle(), name, ec);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void set_verify_callback(T const& fun, error_code& ec)
|
||||
{ m_sock->set_verify_callback(fun, ec); }
|
||||
|
||||
SSL* native_handle() { return m_sock->native_handle(); }
|
||||
{
|
||||
m_sock->set_verify_callback(fun, ec);
|
||||
}
|
||||
|
||||
template <class Handler>
|
||||
void async_connect(endpoint_type const& endpoint, Handler const& h)
|
||||
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018, Alexandre Janniaux
|
||||
Copyright (c) 2020, Paul-Louis Ageneau
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/ssl.hpp"
|
||||
|
||||
#if TORRENT_USE_SSL
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include <openssl/x509v3.h> // for GENERAL_NAME
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_USE_GNUTLS
|
||||
#include <gnutls/x509.h>
|
||||
#endif
|
||||
|
||||
namespace libtorrent {
|
||||
namespace ssl {
|
||||
|
||||
void set_trust_certificate(native_context_type nc, string_view pem, error_code &ec)
|
||||
{
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
// create a new X.509 certificate store
|
||||
X509_STORE* cert_store = X509_STORE_new();
|
||||
if (!cert_store)
|
||||
{
|
||||
ec = error_code(int(ERR_get_error()), error::get_ssl_category());
|
||||
return;
|
||||
}
|
||||
|
||||
// wrap the PEM certificate in a BIO, for openssl to read
|
||||
BIO* bp = BIO_new_mem_buf(
|
||||
const_cast<char*>(pem.data()),
|
||||
int(pem.size()));
|
||||
|
||||
// parse the certificate into OpenSSL's internal representation
|
||||
X509* cert = PEM_read_bio_X509_AUX(bp, nullptr, nullptr, nullptr);
|
||||
BIO_free(bp);
|
||||
|
||||
if (!cert)
|
||||
{
|
||||
X509_STORE_free(cert_store);
|
||||
ec = error_code(int(ERR_get_error()), error::get_ssl_category());
|
||||
return;
|
||||
}
|
||||
|
||||
// add cert to cert_store
|
||||
X509_STORE_add_cert(cert_store, cert);
|
||||
X509_free(cert);
|
||||
|
||||
// and lastly, replace the default cert store with ours
|
||||
SSL_CTX_set_cert_store(nc, cert_store);
|
||||
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
gnutls_datum_t ca;
|
||||
ca.data = reinterpret_cast<unsigned char*>(const_cast<char*>(pem.data()));
|
||||
ca.size = unsigned(pem.size());
|
||||
|
||||
// Warning: returns the number of certificates processed or a negative error code on error
|
||||
int ret = gnutls_certificate_set_x509_trust_mem(nc, &ca, GNUTLS_X509_FMT_PEM);
|
||||
if(ret < 0)
|
||||
ec = error_code(ret, error::get_ssl_category());
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_server_name_callback(context_handle_type c, server_name_callback_type cb, void* arg, error_code& ec)
|
||||
{
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
TORRENT_UNUSED(ec);
|
||||
#if defined __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
SSL_CTX_set_tlsext_servername_callback(c, cb);
|
||||
SSL_CTX_set_tlsext_servername_arg(c, arg);
|
||||
#if defined __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
if(cb)
|
||||
c->set_server_name_callback(
|
||||
[cb, arg](stream_base& s, std::string const& name)
|
||||
{
|
||||
return cb(&s, name, arg);
|
||||
}
|
||||
, ec);
|
||||
else
|
||||
c->set_server_name_callback(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_host_name(stream_handle_type s, std::string const& name, error_code& ec)
|
||||
{
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
TORRENT_UNUSED(ec);
|
||||
#if defined __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
#pragma clang diagnostic ignored "-Wcast-qual"
|
||||
#endif
|
||||
SSL_set_tlsext_host_name(s, name.c_str());
|
||||
#if defined __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
s->set_host_name(name, ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_context(stream_handle_type s, context_handle_type c)
|
||||
{
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
SSL_set_SSL_CTX(s, c);
|
||||
SSL_set_verify(s
|
||||
, SSL_CTX_get_verify_mode(c)
|
||||
, SSL_CTX_get_verify_callback(c));
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
s->set_context(*c);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool has_context(stream_handle_type s, context_handle_type c)
|
||||
{
|
||||
context_handle_type stream_ctx = get_context(s);
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
return stream_ctx == c;
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
return stream_ctx->native_handle() == c->native_handle();
|
||||
#endif
|
||||
}
|
||||
|
||||
context_handle_type get_context(stream_handle_type s)
|
||||
{
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
return SSL_get_SSL_CTX(s);
|
||||
#elif defined TORRENT_USE_GNUTLS
|
||||
return &s->get_context();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined TORRENT_USE_OPENSSL
|
||||
namespace {
|
||||
struct lifecycle
|
||||
{
|
||||
lifecycle()
|
||||
{
|
||||
// this is needed for openssl < 1.0 to decrypt keys created by openssl 1.0+
|
||||
#if !defined(OPENSSL_API_COMPAT) || (OPENSSL_API_COMPAT < 0x10100000L)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
~lifecycle()
|
||||
{
|
||||
// by openssl changelog at https://www.openssl.org/news/changelog.html
|
||||
// Changes between 1.0.2h and 1.1.0 [25 Aug 2016]
|
||||
// - Most global cleanup functions are no longer required because they are handled
|
||||
// via auto-deinit. Affected function CRYPTO_cleanup_all_ex_data()
|
||||
#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
|
||||
#ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
// openssl requires this to clean up internal structures it allocates
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
#ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
} global;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // ssl
|
||||
} // libtorrent
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user