Skip to content

Commit

Permalink
http: implement secure connection
Browse files Browse the repository at this point in the history
cmake: use provided findopenssl module
  • Loading branch information
binarytrails committed Aug 7, 2019
1 parent 4054ec6 commit 49f6dd3
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 89 deletions.
26 changes: 11 additions & 15 deletions CMakeLists.txt
Expand Up @@ -70,19 +70,14 @@ if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
message(SEND_ERROR "Jsoncpp is required for DHT proxy support") message(SEND_ERROR "Jsoncpp is required for DHT proxy support")
endif() endif()
if (OPENDHT_PROXY_OPENSSL) if (OPENDHT_PROXY_OPENSSL)
find_package(OpenSSL REQUIRED) # https://cmake.org/cmake/help/latest/module/FindOpenSSL.html
if (NOT OpenSSL_FOUND) pkg_search_module(OPENSSL REQUIRED openssl)
message(SEND_ERROR "OpenSSL is required for DHT proxy as specified") if (OPENSSL_FOUND)
else () message(STATUS "Found OpenSSL ${OPENSSL_VERSION}")
message("OpenSSL found") include_directories(${OPENSSL_INCLUDE_DIRS})
add_library(ssl SHARED IMPORTED)
add_definitions(-DOPENDHT_PROXY_OPENSSL) add_definitions(-DOPENDHT_PROXY_OPENSSL)
find_package(Crypto REQUIRED) else ()
if (NOT Crypto_FOUND) message(SEND_ERROR "OpenSSL is required for DHT proxy as specified")
message(SEND_ERROR "libcrypto is required for openssl")
else ()
add_library(crypto SHARED IMPORTED)
endif()
endif() endif()
endif() endif()
endif() endif()
Expand Down Expand Up @@ -288,7 +283,7 @@ if (OPENDHT_STATIC)
PRIVATE ${argon2_LIBRARIES} PRIVATE ${argon2_LIBRARIES}
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_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}) ${OPENSSL_LIBRARIES})
install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht) install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif () endif ()


Expand All @@ -307,9 +302,9 @@ if (OPENDHT_SHARED)
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS}) target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
endif () endif ()
target_link_libraries(opendht target_link_libraries(opendht
PUBLIC ${CMAKE_THREAD_LIBS_INIT} PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES}
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
${Jsoncpp_LIBRARIES} ${Crypto_LIBRARIES} ${OpenSSL_LIBRARY} ${Jsoncpp_LIBRARIES}
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY}) ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})


install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht) install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
Expand Down Expand Up @@ -381,6 +376,7 @@ if (OPENDHT_TESTS)
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
${CPPUNIT_LIBRARIES} ${CPPUNIT_LIBRARIES}
${GNUTLS_LIBRARIES} ${GNUTLS_LIBRARIES}
ssl crypto
) )
enable_testing() enable_testing()
add_test(TEST opendht_unit_tests) add_test(TEST opendht_unit_tests)
Expand Down
21 changes: 0 additions & 21 deletions cmake/FindCrypto.cmake

This file was deleted.

22 changes: 0 additions & 22 deletions cmake/FindOpenSSL.cmake

This file was deleted.

17 changes: 10 additions & 7 deletions include/opendht/http.h
Expand Up @@ -33,10 +33,11 @@
namespace http { namespace http {


using HandlerCb = std::function<void(const asio::error_code& ec)>; using HandlerCb = std::function<void(const asio::error_code& ec)>;
using ConnectHandlerCb = std::function<void(const asio::error_code& ec,
const asio::ip::tcp::endpoint& endpoint)>;


#ifdef OPENDHT_PROXY_OPENSSL #ifdef OPENDHT_PROXY_OPENSSL
using socket_t = restinio::impl::tls_socket_t; using socket_t = restinio::impl::tls_socket_t;
//using socket_t = asio::ssl::stream<asio::ip::tcp::socket>;
#else #else
using socket_t = asio::ip::tcp::socket; using socket_t = asio::ip::tcp::socket;
#endif #endif
Expand All @@ -57,31 +58,33 @@ class OPENDHT_PUBLIC Connection
bool is_v6(); bool is_v6();


void set_endpoint(const asio::ip::tcp::endpoint& endpoint); void set_endpoint(const asio::ip::tcp::endpoint& endpoint);
#ifdef OPENDHT_PROXY_OPENSSL
void set_verify_certificate(const std::string hostname, const asio::ssl::verify_mode verify_mode);
#endif


asio::streambuf& input(); asio::streambuf& input();
asio::streambuf& data(); asio::streambuf& data();


std::string read_bytes(const size_t bytes); std::string read_bytes(const size_t bytes);
std::string read_until(const char delim); std::string read_until(const char delim);


#ifdef OPENDHT_PROXY_OPENSSL
socket_t& get_socket();
#else
socket_t& get_socket(); socket_t& get_socket();

void async_connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, ConnectHandlerCb);
#ifdef OPENDHT_PROXY_OPENSSL
void async_handshake(HandlerCb cb);
#endif #endif


void timeout(const std::chrono::seconds timeout, HandlerCb cb = {}); void timeout(const std::chrono::seconds timeout, HandlerCb cb = {});


void close();

private: private:
unsigned int id_; unsigned int id_;
static unsigned int ids_; static unsigned int ids_;


asio::io_context& ctx_; asio::io_context& ctx_;
std::unique_ptr<socket_t> socket_; std::unique_ptr<socket_t> socket_;
#ifdef OPENDHT_PROXY_OPENSSL #ifdef OPENDHT_PROXY_OPENSSL
std::unique_ptr<asio::ssl::context> ssl_ctx_; std::shared_ptr<asio::ssl::context> ssl_ctx_;
asio::ssl::context::options ssl_options_; asio::ssl::context::options ssl_options_;
#endif #endif


Expand Down
79 changes: 55 additions & 24 deletions src/http.cpp
Expand Up @@ -37,15 +37,10 @@ Connection::Connection(asio::io_context& ctx, asio::ssl::context_base::method&&
std::shared_ptr<dht::Logger> l) std::shared_ptr<dht::Logger> l)
: id_(Connection::ids_++), ctx_(ctx), logger_(l) : id_(Connection::ids_++), ctx_(ctx), logger_(l)
{ {
ssl_ctx_ = std::make_unique<asio::ssl::context>(std::move(ssl_method)); ssl_ctx_ = std::make_shared<asio::ssl::context>(std::move(ssl_method));
ssl_ctx_->set_default_verify_paths(); 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_->set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
/* socket_ = std::make_unique<socket_t>(ctx_, ssl_ctx_);
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 #else
Connection::Connection(asio::io_context& ctx, std::shared_ptr<dht::Logger> l) Connection::Connection(asio::io_context& ctx, std::shared_ptr<dht::Logger> l)
Expand All @@ -55,7 +50,13 @@ Connection::Connection(asio::io_context& ctx, std::shared_ptr<dht::Logger> l)


Connection::~Connection() Connection::~Connection()
{ {
close(); if (is_open()){
#ifdef OPENDHT_PROXY_OPENSSL
get_socket().cancel();
get_socket().shutdown(asio::ip::tcp::socket::shutdown_both);
#endif
get_socket().close();
}
socket_.reset(); socket_.reset();
} }


Expand Down Expand Up @@ -112,17 +113,35 @@ Connection::read_until(const char delim)
return content; return content;
} }


#ifdef OPENDHT_PROXY_OPENSSL
socket_t& socket_t&
Connection::get_socket() Connection::get_socket()
{ {
return *socket_; return *socket_;
} }

void
Connection::async_connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, ConnectHandlerCb cb)
{
#ifdef OPENDHT_PROXY_OPENSSL
asio::async_connect(get_socket().lowest_layer(),
#else #else
socket_t& asio::async_connect(get_socket(),
Connection::get_socket() #endif
std::move(endpoints), cb);
}

#ifdef OPENDHT_PROXY_OPENSSL
void
Connection::set_verify_certificate(const std::string hostname, const asio::ssl::verify_mode verify_mode)
{ {
return *socket_; socket_->asio_ssl_stream().set_verify_mode(verify_mode);
socket_->asio_ssl_stream().set_verify_callback(asio::ssl::rfc2818_verification(hostname));
}

void
Connection::async_handshake(HandlerCb cb)
{
socket_->async_handshake(asio::ssl::stream<asio::ip::tcp::socket>::client, cb);
} }
#endif #endif


Expand All @@ -149,12 +168,6 @@ Connection::timeout(const std::chrono::seconds timeout, HandlerCb cb)
}); });
} }


void
Connection::close()
{
get_socket().close();
}

// connection listener // connection listener


ConnectionListener::ConnectionListener() ConnectionListener::ConnectionListener()
Expand Down Expand Up @@ -571,12 +584,10 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
} }
} }
conn_ = std::make_shared<Connection>(ctx_, asio::ssl::context::sslv23); conn_ = std::make_shared<Connection>(ctx_, asio::ssl::context::sslv23);
asio::async_connect(conn_->get_socket().lowest_layer(),
#else #else
conn_ = std::make_shared<Connection>(ctx_); conn_ = std::make_shared<Connection>(ctx_);
asio::async_connect(conn_->get_socket(),
#endif #endif
std::move(endpoints), [this, cb] conn_->async_connect(std::move(endpoints), [this, cb]
(const asio::error_code& ec, const asio::ip::tcp::endpoint& endpoint){ (const asio::error_code& ec, const asio::ip::tcp::endpoint& endpoint){
// try to connect to any until one works // try to connect to any until one works
if (ec == asio::error::operation_aborted) if (ec == asio::error::operation_aborted)
Expand All @@ -591,8 +602,24 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
// save the associated endpoint // save the associated endpoint
conn_->set_endpoint(endpoint); conn_->set_endpoint(endpoint);
} }
#ifdef OPENDHT_PROXY_OPENSSL
conn_->set_verify_certificate(endpoint.address().to_string(), asio::ssl::stream_base::client);
conn_->async_handshake([this, cb](const asio::error_code& ec){
if (ec){
if (logger_)
logger_->e("[http:request:%i] [connect:ssl] error: %s", id_, ec.message().c_str());
}
else {
if (logger_)
logger_->d("[http:request:%i] [connect:ssl] secure channel established", id_);
}
if (cb)
cb(ec);
});
#else
if (cb) if (cb)
cb(ec); cb(ec);
#endif
}); });
} }


Expand Down Expand Up @@ -644,8 +671,12 @@ Request::post()


// send the request // send the request
notify_state_change(State::SENDING); notify_state_change(State::SENDING);
asio::async_write(conn_->get_socket(), conn_->input(), #ifdef OPENDHT_PROXY_OPENSSL
std::bind(&Request::handle_request, this, std::placeholders::_1)); asio::async_write(conn_->get_socket(),
#else
asio::async_write(conn_->get_socket(),
#endif
conn_->input(), std::bind(&Request::handle_request, this, std::placeholders::_1));
} }


void void
Expand All @@ -656,7 +687,7 @@ Request::terminate(const asio::error_code& ec)
logger_->e("[http:request:%i] end with error: %s", id_, ec.message().c_str()); logger_->e("[http:request:%i] end with error: %s", id_, ec.message().c_str());


// close the connection cancelling the scheduled socket operations on the io_context // close the connection cancelling the scheduled socket operations on the io_context
conn_->close(); conn_.reset();
// reset the http_parser holding the data pointer to the user callbacks // reset the http_parser holding the data pointer to the user callbacks
parser_.reset(); parser_.reset();
parser_s_.reset(); parser_s_.reset();
Expand Down

0 comments on commit 49f6dd3

Please sign in to comment.