opendht: add ssl to build system

http: enforce ssl everywhere
This commit is contained in:
Seva committed 2019-08-05 11:09:18 -04:00
1 parent 7ea40c292b
commit 4054ec6af0
5 files changed
+157 -22

No files matched your search

+23 -2
View File
@@ -20,6 +20,7 @@ option (OPENDHT_PROXY_SERVER "Enable DHT proxy server, use Restinio and jsoncpp"
option (OPENDHT_PUSH_NOTIFICATIONS "Enable push notifications support" OFF)
option (OPENDHT_PROXY_SERVER_IDENTITY "Allow clients to use the node identity" OFF)
option (OPENDHT_PROXY_CLIENT "Enable DHT proxy client, use Restinio and jsoncpp" OFF)
option (OPENDHT_PROXY_OPENSSL "Build DHT proxy with OpenSSL" ON)
option (OPENDHT_INDEX "Build DHT indexation feature" OFF)
option (OPENDHT_TESTS "Add unit tests executable" OFF)
@@ -68,6 +69,22 @@ if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
if (NOT Jsoncpp_FOUND)
message(SEND_ERROR "Jsoncpp is required for DHT proxy support")
endif()
if (OPENDHT_PROXY_OPENSSL)
find_package(OpenSSL REQUIRED)
if (NOT OpenSSL_FOUND)
message(SEND_ERROR "OpenSSL is required for DHT proxy as specified")
else ()
message("OpenSSL found")
add_library(ssl SHARED IMPORTED)
add_definitions(-DOPENDHT_PROXY_OPENSSL)
find_package(Crypto REQUIRED)
if (NOT Crypto_FOUND)
message(SEND_ERROR "libcrypto is required for openssl")
else ()
add_library(crypto SHARED IMPORTED)
endif()
endif()
endif()
endif()
# Build flags
@@ -112,6 +129,9 @@ endif ()
if (Jsoncpp_INCLUDE_DIRS)
include_directories (SYSTEM "${Jsoncpp_INCLUDE_DIRS}")
endif ()
if (OpenSSL_INCLUDE_DIR)
include_directories (SYSTEM "${OpenSSL_INCLUDE_DIR}")
endif ()
link_directories (${Nettle_LIBRARY_DIRS})
link_directories (${Jsoncpp_LIBRARY_DIRS})
include_directories (
@@ -267,7 +287,8 @@ if (OPENDHT_STATIC)
target_link_libraries(opendht-static
PRIVATE ${argon2_LIBRARIES}
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
${Jsoncpp_LIBRARIES} ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})
${Jsoncpp_LIBRARIES} ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY}
${Crypto_LIBRARIES} ${OpenSSL_LIBRARY})
install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif ()
@@ -288,7 +309,7 @@ if (OPENDHT_SHARED)
target_link_libraries(opendht
PUBLIC ${CMAKE_THREAD_LIBS_INIT}
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
${Jsoncpp_LIBRARIES}
${Jsoncpp_LIBRARIES} ${Crypto_LIBRARIES} ${OpenSSL_LIBRARY}
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})
install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
+21
View File
@@ -0,0 +1,21 @@
if (NOT Crypto_FOUND)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_search_module(Crypto REQUIRED libcrypto)
endif()
find_library (Crypto_LIBRARY
NAMES crypto
HINTS ${Crypto_ROOT_DIR}
${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
PATHS /usr/local/lib
/usr/lib
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Crypto DEFAULT_MSG Crypto_LIBRARY)
if (Crypto_LIBRARY)
set(Crypto_LIBRARIES ${Crypto_LIBRARY})
message("Found libcrypto library: " ${Crypto_LIBRARIES})
set(Crypto_FOUND TRUE)
endif()
endif()
+22
View File
@@ -0,0 +1,22 @@
if (NOT OpenSSL_FOUND)
find_path (OpenSSL_INCLUDE_DIR openssl
HINTS
"/usr/include"
"/usr/local/include"
"/opt/local/include")
find_library (OpenSSL_LIBRARY
NAMES ssl openssl
HINTS ${OpenSSL_ROOT_DIR}
${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
PATHS /usr/local/lib
/usr/lib
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenSSL DEFAULT_MSG OpenSSL_INCLUDE_DIR OpenSSL_LIBRARY)
if (OpenSSL_INCLUDE_DIR AND OpenSSL_LIBRARY)
message("Found OpenSSL library: " ${OpenSSL_LIBRARY})
message("Found OpenSSL includes: " ${OpenSSL_INCLUDE_DIR})
set(OpenSSL_FOUND TRUE)
endif()
endif()
+30 -3
View File
@@ -19,9 +19,13 @@
#pragma once
#include <asio.hpp>
#ifdef OPENDHT_PROXY_OPENSSL
#include "asio/ssl.hpp"
#endif
#include <json/json.h>
#include <http_parser.h>
#include <restinio/all.hpp>
#include <restinio/impl/tls_socket.hpp>
#include <opendht.h>
#include <opendht/def.h>
#include <opendht/log.h>
@@ -30,10 +34,22 @@ namespace http {
using HandlerCb = std::function<void(const asio::error_code& ec)>;
#ifdef OPENDHT_PROXY_OPENSSL
using socket_t = restinio::impl::tls_socket_t;
//using socket_t = asio::ssl::stream<asio::ip::tcp::socket>;
#else
using socket_t = asio::ip::tcp::socket;
#endif
class OPENDHT_PUBLIC Connection
{
public:
Connection(asio::io_context& ctx, std::shared_ptr<dht::Logger> logger = {});
#ifdef OPENDHT_PROXY_OPENSSL
Connection(asio::io_context& ctx, asio::ssl::context_base::method&& ssl_method,
std::shared_ptr<dht::Logger> l = {});
#else
Connection(asio::io_context& ctx, std::shared_ptr<dht::Logger> l = {});
#endif
~Connection();
unsigned int id();
@@ -48,7 +64,11 @@ public:
std::string read_bytes(const size_t bytes);
std::string read_until(const char delim);
asio::ip::tcp::socket& socket();
#ifdef OPENDHT_PROXY_OPENSSL
socket_t& get_socket();
#else
socket_t& get_socket();
#endif
void timeout(const std::chrono::seconds timeout, HandlerCb cb = {});
@@ -58,7 +78,13 @@ private:
unsigned int id_;
static unsigned int ids_;
asio::ip::tcp::socket socket_;
asio::io_context& ctx_;
std::unique_ptr<socket_t> socket_;
#ifdef OPENDHT_PROXY_OPENSSL
std::unique_ptr<asio::ssl::context> ssl_ctx_;
asio::ssl::context::options ssl_options_;
#endif
asio::ip::tcp::endpoint endpoint_;
asio::streambuf write_buf_;
@@ -174,6 +200,7 @@ public:
~Request();
unsigned int id() const;
void set_connection(std::shared_ptr<Connection> connection);
std::shared_ptr<Connection> get_connection() const;
void set_logger(std::shared_ptr<dht::Logger> logger);
+61 -17
View File
@@ -32,13 +32,31 @@ constexpr char JSON_VALUE_DELIM = '\n';
unsigned int Connection::ids_ = 1;
Connection::Connection(asio::io_context& ctx, std::shared_ptr<dht::Logger> logger):
id_(Connection::ids_++), socket_(ctx), logger_(logger)
#ifdef OPENDHT_PROXY_OPENSSL
Connection::Connection(asio::io_context& ctx, asio::ssl::context_base::method&& ssl_method,
std::shared_ptr<dht::Logger> l)
: id_(Connection::ids_++), ctx_(ctx), logger_(l)
{
ssl_ctx_ = std::make_unique<asio::ssl::context>(std::move(ssl_method));
ssl_ctx_->set_default_verify_paths();
ssl_ctx_->set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
/*
ssl_ctx_->use_certificate_chain_file(chain_file);
ssl_ctx_->use_private_key_file(key_file, asio::ssl::context::pem);
get_socket().set_verify_callback(asio::ssl::rfc2818_verification(host_name));
socket_ = std::make_unique<ssl_socket_t>(ctx_, ssl_ctx_.get());
*/
}
#else
Connection::Connection(asio::io_context& ctx, std::shared_ptr<dht::Logger> l)
: id_(Connection::ids_++), ctx_(ctx), socket_(new socket_t(ctx)), logger_(l)
{}
#endif
Connection::~Connection()
{
close();
socket_.reset();
}
unsigned int
@@ -50,7 +68,7 @@ Connection::id()
bool
Connection::is_open()
{
return socket_.is_open();
return get_socket().is_open();
}
bool
@@ -94,11 +112,19 @@ Connection::read_until(const char delim)
return content;
}
asio::ip::tcp::socket&
Connection::socket()
#ifdef OPENDHT_PROXY_OPENSSL
socket_t&
Connection::get_socket()
{
return socket_;
return *socket_;
}
#else
socket_t&
Connection::get_socket()
{
return *socket_;
}
#endif
void
Connection::timeout(const std::chrono::seconds timeout, HandlerCb cb)
@@ -109,7 +135,7 @@ Connection::timeout(const std::chrono::seconds timeout, HandlerCb cb)
return;
}
if (!timeout_timer_)
timeout_timer_ = std::make_unique<asio::steady_timer>(socket_.get_io_context());
timeout_timer_ = std::make_unique<asio::steady_timer>(ctx_);
timeout_timer_->expires_at(std::chrono::steady_clock::now() + timeout);
timeout_timer_->async_wait([this, cb](const asio::error_code &ec){
if (ec == asio::error::operation_aborted)
@@ -126,7 +152,7 @@ Connection::timeout(const std::chrono::seconds timeout, HandlerCb cb)
void
Connection::close()
{
socket_.close();
get_socket().close();
}
// connection listener
@@ -310,6 +336,12 @@ Request::id() const
return id_;
}
void
Request::set_connection(std::shared_ptr<Connection> connection)
{
conn_ = connection;
}
std::shared_ptr<Connection>
Request::get_connection() const
{
@@ -530,11 +562,23 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
eps.append(endpoint.address().to_string() + " ");
logger_->d("[http:request:%i] [connect] begin endpoints { %s}", id_, eps.c_str());
}
conn_ = std::make_shared<Connection>(ctx_);
#ifdef OPENDHT_PROXY_OPENSSL
if (service_ == "https" or service_ == "443"){
if (!conn_){
logger_->e("[http:request:%i] [connect] undefined SSL connection", id_);
terminate(asio::error::connection_aborted);
}
}
conn_ = std::make_shared<Connection>(ctx_, asio::ssl::context::sslv23);
asio::async_connect(conn_->get_socket().lowest_layer(),
#else
conn_ = std::make_shared<Connection>(ctx_);
asio::async_connect(conn_->get_socket(),
#endif
std::move(endpoints), [this, cb]
(const asio::error_code& ec, const asio::ip::tcp::endpoint& endpoint){
// try to connect to any until one works
asio::async_connect(conn_->socket(), std::move(endpoints), [this, cb]
(const asio::error_code& ec, const asio::ip::tcp::endpoint& endpoint){
if (ec == asio::error::operation_aborted)
return;
else if (ec){
@@ -600,7 +644,7 @@ Request::post()
// send the request
notify_state_change(State::SENDING);
asio::async_write(conn_->socket(), conn_->input(),
asio::async_write(conn_->get_socket(), conn_->input(),
std::bind(&Request::handle_request, this, std::placeholders::_1));
}
@@ -651,7 +695,7 @@ Request::handle_request(const asio::error_code& ec)
// read response
notify_state_change(State::RECEIVING);
asio::async_read_until(conn_->socket(), conn_->data(), HTTP_HEADER_DELIM,
asio::async_read_until(conn_->get_socket(), conn_->data(), HTTP_HEADER_DELIM,
std::bind(&Request::handle_response_header, this, std::placeholders::_1));
}
@@ -704,7 +748,7 @@ Request::handle_response_header(const asio::error_code& ec)
terminate(asio::error::eof);
}
else { // more chunks to come (don't add the missing \n from std::getline)
asio::async_read(conn_->socket(), conn_->data(),
asio::async_read(conn_->get_socket(), conn_->data(),
asio::transfer_exactly(content_length - response_.body.size()),
std::bind(&Request::handle_response_body, this, std::placeholders::_1, std::placeholders::_2));
}
@@ -712,7 +756,7 @@ Request::handle_response_header(const asio::error_code& ec)
// server wants to keep sending or we have content-length defined
else if (response_.headers[HTTP_HEADER_CONNECTION] == HTTP_HEADER_CONNECTION_KEEP_ALIVE)
{
asio::async_read_until(conn_->socket(), conn_->data(), JSON_VALUE_DELIM,
asio::async_read_until(conn_->get_socket(), conn_->data(), JSON_VALUE_DELIM,
std::bind(&Request::handle_response_body, this, std::placeholders::_1, std::placeholders::_2));
}
else if (connection_type_ == restinio::http_connection_header_t::close)
@@ -767,12 +811,12 @@ Request::handle_response_body(const asio::error_code& ec, const size_t bytes)
}
// has content-length
else if (content_length_it != response_.headers.end() and response_.body.size() != content_length)
asio::async_read(conn_->socket(), conn_->data(),
asio::async_read(conn_->get_socket(), conn_->data(),
asio::transfer_exactly(content_length - response_.body.size()),
std::bind(&Request::handle_response_body, this, std::placeholders::_1, std::placeholders::_2));
// server wants to keep sending
else if (response_.headers[HTTP_HEADER_CONNECTION] == HTTP_HEADER_CONNECTION_KEEP_ALIVE){
asio::async_read_until(conn_->socket(), conn_->data(), JSON_VALUE_DELIM,
asio::async_read_until(conn_->get_socket(), conn_->data(), JSON_VALUE_DELIM,
std::bind(&Request::handle_response_body, this, std::placeholders::_1, std::placeholders::_2));
}
else if (connection_type_ == restinio::http_connection_header_t::close)