Commit 1e81bfb5 authored by Robin Sommer's avatar Robin Sommer Committed by Dominik Charousset

Adressing PR feedback.

parent 1135449e
...@@ -11,7 +11,7 @@ set (LIBCAF_OPENSSL_SRCS ...@@ -11,7 +11,7 @@ set (LIBCAF_OPENSSL_SRCS
src/middleman_actor.cpp src/middleman_actor.cpp
src/publish.cpp src/publish.cpp
src/remote_actor.cpp src/remote_actor.cpp
src/ssl_session.cpp) src/session.cpp)
add_custom_target(libcaf_openssl) add_custom_target(libcaf_openssl)
......
...@@ -17,24 +17,24 @@ ...@@ -17,24 +17,24 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#ifndef CAF_OPENSSL_SSL_SESSION_HPP #ifndef CAF_OPENSSL_SESSION_HPP
#define CAF_OPENSSL_SSL_SESSION_HPP #define CAF_OPENSSL_SESSION_HPP
#include "caf/actor_system.hpp" #include "caf/actor_system.hpp"
#include "caf/io/network/native_socket.hpp" #include "caf/io/network/native_socket.hpp"
#include <openssl/err.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
namespace caf { namespace caf {
namespace openssl { namespace openssl {
using native_socket = io::network::native_socket; using native_socket = io::network::native_socket;
class ssl_session { class session : public ref_counted {
public: public:
ssl_session(actor_system& sys); session(actor_system& sys);
~ssl_session(); ~session();
void init();
bool read_some(size_t& result, native_socket fd, void* buf, size_t len); bool read_some(size_t& result, native_socket fd, void* buf, size_t len);
bool write_some(size_t& result, native_socket fd, const void* buf, bool write_some(size_t& result, native_socket fd, const void* buf,
size_t len); size_t len);
...@@ -43,17 +43,18 @@ public: ...@@ -43,17 +43,18 @@ public:
const char* openssl_passphrase(); const char* openssl_passphrase();
private: private:
SSL_CTX* create_ssl_context(actor_system& sys); SSL_CTX* create_ssl_context();
std::string get_ssl_error(); std::string get_ssl_error();
void raise_ssl_error(std::string msg); void raise_ssl_error(std::string msg);
bool handle_ssl_result(int ret); bool handle_ssl_result(int ret);
SSL_CTX* ctx; actor_system& sys_;
SSL* ssl; SSL_CTX* ctx_;
SSL* ssl_;
std::string openssl_passphrase_; std::string openssl_passphrase_;
}; };
} // namespace openssl } // namespace openssl
} // namespace caf } // namespace caf
#endif // CAF_OPENSSL_SSL_SESSION_HPP #endif // CAF_OPENSSL_SESSION_HPP
...@@ -58,17 +58,14 @@ void manager::stop() { ...@@ -58,17 +58,14 @@ void manager::stop() {
void manager::init(actor_system_config&) { void manager::init(actor_system_config&) {
CAF_LOG_TRACE(""); CAF_LOG_TRACE("");
ERR_load_crypto_strings(); ERR_load_crypto_strings();
OPENSSL_add_all_algorithms_conf(); OPENSSL_add_all_algorithms_conf();
SSL_library_init(); SSL_library_init();
SSL_load_error_strings(); SSL_load_error_strings();
if (authentication_enabled()) { if (authentication_enabled()) {
if (!system().config().openssl_certificate.size()) if (system().config().openssl_certificate.size() == 0)
CAF_RAISE_ERROR("No certificate configured for SSL endpoint"); CAF_RAISE_ERROR("No certificate configured for SSL endpoint");
if (system().config().openssl_key.size() == 0)
if (!system().config().openssl_key.size())
CAF_RAISE_ERROR("No private key configured for SSL endpoint"); CAF_RAISE_ERROR("No private key configured for SSL endpoint");
} }
} }
...@@ -83,9 +80,9 @@ void* manager::subtype_ptr() { ...@@ -83,9 +80,9 @@ void* manager::subtype_ptr() {
bool manager::authentication_enabled() { bool manager::authentication_enabled() {
auto& cfg = system().config(); auto& cfg = system().config();
return cfg.openssl_certificate.size() || cfg.openssl_key.size() return cfg.openssl_certificate.size() > 0 || cfg.openssl_key.size() > 0
|| cfg.openssl_passphrase.size() || cfg.openssl_capath.size() || cfg.openssl_passphrase.size() > 0 || cfg.openssl_capath.size() > 0
|| cfg.openssl_cafile.size(); || cfg.openssl_cafile.size() > 0;
} }
actor_system::module* manager::make(actor_system& sys, detail::type_list<>) { actor_system::module* manager::make(actor_system& sys, detail::type_list<>) {
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include "caf/io/network/interfaces.hpp" #include "caf/io/network/interfaces.hpp"
#include "caf/io/network/default_multiplexer.hpp" #include "caf/io/network/default_multiplexer.hpp"
#include "caf/openssl/ssl_session.hpp" #include "caf/openssl/session.hpp"
namespace caf { namespace caf {
namespace openssl { namespace openssl {
...@@ -50,53 +50,47 @@ using native_socket = io::network::native_socket; ...@@ -50,53 +50,47 @@ using native_socket = io::network::native_socket;
using default_mpx = io::network::default_multiplexer; using default_mpx = io::network::default_multiplexer;
struct ssl_policy { struct ssl_policy {
ssl_policy(std::shared_ptr<ssl_session> ssl) : ssl_(ssl) { ssl_policy(intrusive_ptr<session> session) : session_(std::move(session)) {
} }
bool read_some(size_t& result, native_socket fd, void* buf, bool read_some(size_t& result, native_socket fd, void* buf,
size_t len) { size_t len) {
CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(len)); CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(len));
return session_->read_some(result, fd, buf, len);
return ssl_->read_some(result, fd, buf, len);
} }
bool write_some(size_t& result, native_socket fd, const void* buf, bool write_some(size_t& result, native_socket fd, const void* buf,
size_t len) { size_t len) {
CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(len)); CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(len));
return session_->write_some(result, fd, buf, len);
return ssl_->write_some(result, fd, buf, len);
} }
bool try_accept(native_socket& result, native_socket fd) { bool try_accept(native_socket& result, native_socket fd) {
CAF_LOG_TRACE(CAF_ARG(fd)); CAF_LOG_TRACE(CAF_ARG(fd));
sockaddr_storage addr; sockaddr_storage addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
socklen_t addrlen = sizeof(addr); socklen_t addrlen = sizeof(addr);
result = ::accept(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen); result = accept(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen);
CAF_LOG_DEBUG(CAF_ARG(fd) << CAF_ARG(result)); CAF_LOG_DEBUG(CAF_ARG(fd) << CAF_ARG(result));
if (result == io::network::invalid_native_socket) { if (result == io::network::invalid_native_socket) {
auto err = io::network::last_socket_error(); auto err = io::network::last_socket_error();
if (!io::network::would_block_or_temporarily_unavailable(err)) if (!io::network::would_block_or_temporarily_unavailable(err))
return false; return false;
} }
return session_->try_accept(result);
return ssl_->try_accept(result);
} }
private: private:
std::shared_ptr<ssl_session> ssl_; intrusive_ptr<session> session_;
}; };
class scribe_impl : public io::scribe { class scribe_impl : public io::scribe {
public: public:
scribe_impl(default_mpx& mpx, native_socket sockfd, scribe_impl(default_mpx& mpx, native_socket sockfd,
std::shared_ptr<ssl_session> ssl) intrusive_ptr<session> session)
: scribe(io::network::conn_hdl_from_socket(sockfd)), : scribe(io::network::conn_hdl_from_socket(sockfd)),
launched_(false), launched_(false),
stream_(mpx, sockfd, ssl) { stream_(mpx, sockfd, session) {
// nop // nop
} }
...@@ -168,10 +162,10 @@ class scribe_impl : public io::scribe { ...@@ -168,10 +162,10 @@ class scribe_impl : public io::scribe {
class doorman_impl : public io::doorman { class doorman_impl : public io::doorman {
public: public:
doorman_impl(default_mpx& mx, native_socket sockfd, doorman_impl(default_mpx& mx, native_socket sockfd,
std::shared_ptr<ssl_session> ssl) intrusive_ptr<session> session)
: doorman(io::network::accept_hdl_from_socket(sockfd)), : doorman(io::network::accept_hdl_from_socket(sockfd)),
acceptor_(mx, sockfd, ssl), acceptor_(mx, sockfd, session),
ssl_(ssl) { session_(std::move(session)) {
// nop // nop
} }
...@@ -185,7 +179,7 @@ public: ...@@ -185,7 +179,7 @@ public:
return false; return false;
auto& dm = acceptor_.backend(); auto& dm = acceptor_.backend();
auto sptr = auto sptr =
make_counted<scribe_impl>(dm, acceptor_.accepted_socket(), ssl_); make_counted<scribe_impl>(dm, acceptor_.accepted_socket(), session_);
auto hdl = sptr->hdl(); auto hdl = sptr->hdl();
parent()->add_scribe(std::move(sptr)); parent()->add_scribe(std::move(sptr));
return doorman::new_connection(&dm, hdl); return doorman::new_connection(&dm, hdl);
...@@ -226,7 +220,7 @@ public: ...@@ -226,7 +220,7 @@ public:
private: private:
io::network::acceptor_impl<ssl_policy> acceptor_; io::network::acceptor_impl<ssl_policy> acceptor_;
std::shared_ptr<ssl_session> ssl_; intrusive_ptr<session> session_;
}; };
class middleman_actor_impl : public io::middleman_actor_impl { class middleman_actor_impl : public io::middleman_actor_impl {
...@@ -240,14 +234,11 @@ protected: ...@@ -240,14 +234,11 @@ protected:
expected<io::scribe_ptr> connect(const std::string& host, expected<io::scribe_ptr> connect(const std::string& host,
uint16_t port) override { uint16_t port) override {
auto fd = io::network::new_tcp_connection(host, port); auto fd = io::network::new_tcp_connection(host, port);
if (fd == io::network::invalid_native_socket)
if (!fd)
return std::move(fd.error()); return std::move(fd.error());
auto session = new class session(system());
auto ssl = std::make_shared<ssl_session>(system()); if (session->connect(*fd))
return make_counted<scribe_impl>(mpx(), *fd, session);
if (ssl->connect(*fd))
return make_counted<scribe_impl>(mpx(), *fd, ssl);
else else
return sec::cannot_connect_to_node; return sec::cannot_connect_to_node;
} }
...@@ -255,13 +246,10 @@ protected: ...@@ -255,13 +246,10 @@ protected:
expected<io::doorman_ptr> open(uint16_t port, const char* addr, expected<io::doorman_ptr> open(uint16_t port, const char* addr,
bool reuse) override { bool reuse) override {
auto fd = io::network::new_tcp_acceptor_impl(port, addr, reuse); auto fd = io::network::new_tcp_acceptor_impl(port, addr, reuse);
if (fd == io::network::invalid_native_socket)
if (!fd)
return std::move(fd.error()); return std::move(fd.error());
auto session = new class session(system());
auto ssl = std::make_shared<ssl_session>(system()); return make_counted<doorman_impl>(mpx(), *fd, session);
return make_counted<doorman_impl>(mpx(), *fd, ssl);
} }
private: private:
......
...@@ -17,10 +17,12 @@ ...@@ -17,10 +17,12 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#include "caf/openssl/ssl_session.hpp" #include "caf/openssl/session.hpp"
#include <sys/socket.h> #include <sys/socket.h>
#include <openssl/err.h>
#include "caf/actor_system_config.hpp" #include "caf/actor_system_config.hpp"
#include "caf/openssl/manager.hpp" #include "caf/openssl/manager.hpp"
...@@ -29,28 +31,27 @@ namespace openssl { ...@@ -29,28 +31,27 @@ namespace openssl {
static int pem_passwd_cb(char* buf, int size, int rwflag, void* session); static int pem_passwd_cb(char* buf, int size, int rwflag, void* session);
ssl_session::ssl_session(actor_system& sys) { session::session(actor_system& sys) : sys_(sys) {
ctx = create_ssl_context(sys); }
ssl = SSL_new(ctx);
if (!ssl) void session::init() {
ctx_ = create_ssl_context();
ssl_ = SSL_new(ctx_);
if (!ssl_)
CAF_RAISE_ERROR("cannot create SSL session"); CAF_RAISE_ERROR("cannot create SSL session");
} }
ssl_session::~ssl_session() { session::~session() {
SSL_free(ssl); SSL_free(ssl_);
SSL_CTX_free(ctx); SSL_CTX_free(ctx_);
} }
bool ssl_session::read_some(size_t& result, native_socket fd, void* buf, bool session::read_some(size_t& result, native_socket /* fd */, void* buf,
size_t len) { size_t len) {
CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(len)); CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(len));
if (len == 0) if (len == 0)
return 0; return 0;
auto ret = SSL_read(ssl_, buf, len);
auto ret = SSL_read(ssl, buf, len);
if (ret > 0) { if (ret > 0) {
result = ret; result = ret;
return true; return true;
...@@ -60,15 +61,12 @@ bool ssl_session::read_some(size_t& result, native_socket fd, void* buf, ...@@ -60,15 +61,12 @@ bool ssl_session::read_some(size_t& result, native_socket fd, void* buf,
} }
} }
bool ssl_session::write_some(size_t& result, native_socket fd, const void* buf, bool session::write_some(size_t& result, native_socket /* fd */,
size_t len) { const void* buf, size_t len) {
CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(len)); CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(len));
if (len == 0) if (len == 0)
return true; return true;
auto ret = SSL_write(ssl_, buf, len);
auto ret = SSL_write(ssl, buf, len);
if (ret > 0) { if (ret > 0) {
result = ret; result = ret;
return true; return true;
...@@ -78,71 +76,60 @@ bool ssl_session::write_some(size_t& result, native_socket fd, const void* buf, ...@@ -78,71 +76,60 @@ bool ssl_session::write_some(size_t& result, native_socket fd, const void* buf,
} }
} }
bool ssl_session::connect(native_socket fd) { bool session::connect(native_socket fd) {
SSL_set_fd(ssl, fd); init();
SSL_set_connect_state(ssl); SSL_set_fd(ssl_, fd);
SSL_set_connect_state(ssl_);
auto ret = SSL_connect(ssl); auto ret = SSL_connect(ssl_);
return ret > 0 || handle_ssl_result(ret); return ret > 0 || handle_ssl_result(ret);
} }
bool ssl_session::try_accept(native_socket fd) { bool session::try_accept(native_socket fd) {
SSL_set_fd(ssl, fd); init();
SSL_set_accept_state(ssl); SSL_set_fd(ssl_, fd);
SSL_set_accept_state(ssl_);
auto ret = SSL_accept(ssl); auto ret = SSL_accept(ssl_);
if (ret > 0) if (ret > 0)
return true; return true;
else else
return handle_ssl_result(ret); return handle_ssl_result(ret);
} }
const char* ssl_session::openssl_passphrase() { const char* session::openssl_passphrase() {
return openssl_passphrase_.c_str(); return openssl_passphrase_.c_str();
} }
SSL_CTX* ssl_session::create_ssl_context(actor_system& sys) { SSL_CTX* session::create_ssl_context() {
auto ctx = SSL_CTX_new(TLSv1_2_method()); auto ctx = SSL_CTX_new(TLSv1_2_method());
if (!ctx) if (!ctx)
raise_ssl_error("cannot create OpenSSL context"); raise_ssl_error("cannot create OpenSSL context");
if (sys_.openssl_manager().authentication_enabled()) {
if (sys.openssl_manager().authentication_enabled()) {
// Require valid certificates on both sides. // Require valid certificates on both sides.
auto& cfg = sys_.config();
auto& cfg = sys.config(); if (cfg.openssl_certificate.size() > 0
if (cfg.openssl_certificate.size()
&& SSL_CTX_use_certificate_chain_file(ctx, && SSL_CTX_use_certificate_chain_file(ctx,
cfg.openssl_certificate.c_str()) cfg.openssl_certificate.c_str())
!= 1) != 1)
raise_ssl_error("cannot load certificate"); raise_ssl_error("cannot load certificate");
if (cfg.openssl_passphrase.size() > 0) {
if (cfg.openssl_passphrase.size()) {
openssl_passphrase_ = cfg.openssl_passphrase; openssl_passphrase_ = cfg.openssl_passphrase;
SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb); SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)this); SSL_CTX_set_default_passwd_cb_userdata(ctx, (void*)this);
} }
if (cfg.openssl_key.size() > 0
if (cfg.openssl_key.size()
&& SSL_CTX_use_PrivateKey_file(ctx, cfg.openssl_key.c_str(), && SSL_CTX_use_PrivateKey_file(ctx, cfg.openssl_key.c_str(),
SSL_FILETYPE_PEM) SSL_FILETYPE_PEM)
!= 1) != 1)
raise_ssl_error("cannot load private key"); raise_ssl_error("cannot load private key");
auto cafile = auto cafile =
(cfg.openssl_cafile.size() ? cfg.openssl_cafile.c_str() : nullptr); (cfg.openssl_cafile.size() > 0 ? cfg.openssl_cafile.c_str() : nullptr);
auto capath = auto capath =
(cfg.openssl_capath.size() ? cfg.openssl_capath.c_str() : nullptr); (cfg.openssl_capath.size() > 0 ? cfg.openssl_capath.c_str() : nullptr);
if (cafile || capath) { if (cafile || capath) {
if (SSL_CTX_load_verify_locations(ctx, cafile, capath) != 1) if (SSL_CTX_load_verify_locations(ctx, cafile, capath) != 1)
raise_ssl_error("cannot load trusted CA certificates"); raise_ssl_error("cannot load trusted CA certificates");
} }
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr); SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
if (SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!MD5") != 1) if (SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!MD5") != 1)
raise_ssl_error("cannot set cipher list"); raise_ssl_error("cannot set cipher list");
} }
...@@ -150,13 +137,10 @@ SSL_CTX* ssl_session::create_ssl_context(actor_system& sys) { ...@@ -150,13 +137,10 @@ SSL_CTX* ssl_session::create_ssl_context(actor_system& sys) {
else { else {
// No authentication. // No authentication.
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr); SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr);
auto ecdh = EC_KEY_new_by_curve_name(NID_secp384r1); auto ecdh = EC_KEY_new_by_curve_name(NID_secp384r1);
if (!ecdh) if (!ecdh)
raise_ssl_error("cannot get ECDH curve"); raise_ssl_error("cannot get ECDH curve");
SSL_CTX_set_tmp_ecdh(ctx, ecdh); SSL_CTX_set_tmp_ecdh(ctx, ecdh);
if (SSL_CTX_set_cipher_list(ctx, "AECDH-AES256-SHA") != 1) if (SSL_CTX_set_cipher_list(ctx, "AECDH-AES256-SHA") != 1)
raise_ssl_error("cannot set anonymous cipher"); raise_ssl_error("cannot set anonymous cipher");
} }
...@@ -164,37 +148,31 @@ SSL_CTX* ssl_session::create_ssl_context(actor_system& sys) { ...@@ -164,37 +148,31 @@ SSL_CTX* ssl_session::create_ssl_context(actor_system& sys) {
return ctx; return ctx;
} }
std::string ssl_session::get_ssl_error() { std::string session::get_ssl_error() {
std::string msg = ""; std::string msg = "";
while (auto err = ERR_get_error()) { while (auto err = ERR_get_error()) {
if (msg.size()) if (msg.size() > 0)
msg += " "; msg += " ";
char buf[256]; char buf[256];
ERR_error_string_n(err, buf, sizeof(buf)); ERR_error_string_n(err, buf, sizeof(buf));
msg += buf; msg += buf;
} }
return msg; return msg;
} }
void ssl_session::raise_ssl_error(std::string msg) { void session::raise_ssl_error(std::string msg) {
CAF_RAISE_ERROR(std::string("[OpenSSL] ") + msg + ": " + get_ssl_error()); CAF_RAISE_ERROR(std::string("[OpenSSL] ") + msg + ": " + get_ssl_error());
} }
bool ssl_session::handle_ssl_result(int ret) { bool session::handle_ssl_result(int ret) {
auto err = SSL_get_error(ssl, ret); auto err = SSL_get_error(ssl_, ret);
switch (err) { switch (err) {
case SSL_ERROR_WANT_READ: // Try again next time. case SSL_ERROR_WANT_READ: // Try again next time.
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
return true; return true;
case SSL_ERROR_ZERO_RETURN: // Regular remote connection shutdown. case SSL_ERROR_ZERO_RETURN: // Regular remote connection shutdown.
case SSL_ERROR_SYSCALL: // Socket connection closed. case SSL_ERROR_SYSCALL: // Socket connection closed.
return false; return false;
default: // Other error default: // Other error
// TODO: Log somehow? // TODO: Log somehow?
// auto msg = get_ssl_error(); // auto msg = get_ssl_error();
...@@ -203,7 +181,7 @@ bool ssl_session::handle_ssl_result(int ret) { ...@@ -203,7 +181,7 @@ bool ssl_session::handle_ssl_result(int ret) {
} }
static int pem_passwd_cb(char* buf, int size, int /* rwflag */, void* session) { static int pem_passwd_cb(char* buf, int size, int /* rwflag */, void* session) {
auto passphrase = static_cast<ssl_session*>(session)->openssl_passphrase(); auto passphrase = static_cast<class session*>(session)->openssl_passphrase();
strncpy(buf, passphrase, size); strncpy(buf, passphrase, size);
buf[size - 1] = '\0'; buf[size - 1] = '\0';
return strlen(buf); return strlen(buf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment