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