From 40358890af401feb1a31a5e808619528ed97285c Mon Sep 17 00:00:00 2001 From: Ravidu Lashan Date: Thu, 24 Oct 2019 14:54:33 +0530 Subject: [PATCH] Added initial TLS support for socket communication (#41) * Added initial commit * Added tls to web sockets which require key file and cert file * Added meaningful comments --- CMakeLists.txt | 3 +- README.md | 7 ++ src/conf.cpp | 31 +++++-- src/conf.hpp | 34 +++---- src/p2p/p2p.cpp | 10 +- src/p2p/p2p.hpp | 2 +- src/p2p/peer_session_handler.cpp | 6 +- src/sock/socket_client.hpp | 59 ++++-------- src/sock/socket_server.hpp | 108 ++++++++++++---------- src/sock/socket_session.hpp | 152 +++++++++++++++++++------------ src/usr/user_session_handler.cpp | 14 +-- src/usr/usr.cpp | 9 +- 12 files changed, 248 insertions(+), 187 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e7c0863..bc1ea96f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,5 +34,6 @@ target_link_libraries(hpcore ${Boost_LOG_SETUP_LIBRARY} stdc++fs pthread - protobuf.a + crypto + ssl ) \ No newline at end of file diff --git a/README.md b/README.md index 84ee9d59..6cbfe0d2 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,13 @@ When you make a change to `message.fbc` defnition file, you need to run this: `flatc -o src/p2p/ --gen-mutable --cpp src/p2p/message.fbs` +#### Install OpenSSL +1. Download and extract OpenSSL-1.1.1d source from [here](https://www.openssl.org/source/openssl-1.1.1d.tar.gz). +2. Navigate to the extracted directory. +3. Run `./config` +4. Run `make` +5. Run `make install` + #### Run ldconfig `sudo ldconfig` diff --git a/src/conf.cpp b/src/conf.cpp index 578d9d1c..f02b25e0 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -123,6 +123,8 @@ void set_contract_dir_paths(std::string basedir) ctx.contractDir = basedir; ctx.configDir = basedir + "/cfg"; ctx.configFile = ctx.configDir + "/hp.cfg"; + ctx.tlsKeyFile = ctx.configDir + "/key.pem"; + ctx.tlsCertFile = ctx.configDir + "/cert.pem"; ctx.histDir = basedir + "/hist"; ctx.stateDir = basedir + "/state"; ctx.logDir = basedir + "/log"; @@ -190,14 +192,14 @@ int load_config() cfg.peers.clear(); for (auto &v : d["peers"].GetArray()) { - const char* ipport_concat = v.GetString(); + const char *ipport_concat = v.GetString(); // Split the address:port text into two boost::split(splitted_peers, ipport_concat, boost::is_any_of(":")); if (splitted_peers.size() == 2) { - // Push the peer address and the port to peers array - cfg.peers.emplace(std::make_pair(ipport_concat, std::make_pair(splitted_peers.front(), splitted_peers.back()))); - splitted_peers.clear(); + // Push the peer address and the port to peers array + cfg.peers.emplace(std::make_pair(ipport_concat, std::make_pair(splitted_peers.front(), splitted_peers.back()))); + splitted_peers.clear(); } } @@ -234,8 +236,7 @@ int load_config() return -1; return 0; -} - +} /** * Saves the current values of the 'cfg' struct into the config file. * @@ -440,13 +441,23 @@ int validate_config() */ int validate_contract_dir_paths() { - std::string dirs[4] = {ctx.contractDir, ctx.configFile, ctx.histDir, ctx.stateDir}; + std::string paths[6] = {ctx.contractDir, ctx.configFile, ctx.histDir, ctx.stateDir, ctx.tlsKeyFile, ctx.tlsCertFile}; - for (std::string &dir : dirs) + for (std::string &path : paths) { - if (!std::experimental::filesystem::exists(dir)) + if (!std::experimental::filesystem::exists(path)) { - std::cout << dir << " does not exist.\n"; + if(path == ctx.tlsKeyFile || path == ctx.tlsCertFile) + { + std::cout << path << " does not exist. Please provide self-signed certificates. Can generate using command\n" << + "openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem\n" << + "and add it to "+ ctx.configDir; + } + else + { + std::cout << path << " does not exist.\n"; + } + return -1; } } diff --git a/src/conf.hpp b/src/conf.hpp index 37aba685..f04a5a77 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -14,7 +14,7 @@ namespace conf { // Typedef to represent ip address and port pair. -typedef std::pair ip_port_pair; +typedef std::pair ip_port_pair; // Holds contextual information about the currently loaded contract. struct contract_ctx @@ -27,6 +27,8 @@ struct contract_ctx std::string logDir; // Contract log dir std::string configDir; // Contract config dir std::string configFile; // Full path to the contract config file + std::string tlsKeyFile; // Full path to the tls secret key file + std::string tlsCertFile; // Full path to the tls certificate }; // Holds all the contract config values. @@ -39,21 +41,21 @@ struct contract_config // Config elements which are loaded from the config file. - std::string pubkeyhex; // Contract hex public key - std::string seckeyhex; // Contract hex secret key - std::string keytype; // Key generation algorithm used by libsodium - std::string binary; // Full path to the contract binary - std::string binargs; // CLI arguments to pass to the contract binary - std::string listenip; // The IPs to listen on for incoming connections - std::unordered_map peers; // Map of peers keyed by ":" concatenated format - std::unordered_set unl; // Unique node list (list of binary public keys) - std::uint16_t peerport; // Listening port for peer connections - int roundtime; // Consensus round time in ms - std::uint16_t pubport; // Listening port for public user connections - int pubmaxsize; // User message max size in bytes - int pubmaxcpm; // User message rate - std::string loglevel; // Log severity level (debug, info, warn, error) - std::unordered_set loggers; // List of enabled loggers (console, file) + std::string pubkeyhex; // Contract hex public key + std::string seckeyhex; // Contract hex secret key + std::string keytype; // Key generation algorithm used by libsodium + std::string binary; // Full path to the contract binary + std::string binargs; // CLI arguments to pass to the contract binary + std::string listenip; // The IPs to listen on for incoming connections + std::unordered_map peers; // Map of peers keyed by ":" concatenated format + std::unordered_set unl; // Unique node list (list of binary public keys) + std::uint16_t peerport; // Listening port for peer connections + int roundtime; // Consensus round time in ms + std::uint16_t pubport; // Listening port for public user connections + int pubmaxsize; // User message max size in bytes + int pubmaxcpm; // User message rate + std::string loglevel; // Log severity level (debug, info, warn, error) + std::unordered_set loggers; // List of enabled loggers (console, file) }; // Global contract context struct exposed to the application. diff --git a/src/p2p/p2p.cpp b/src/p2p/p2p.cpp index 11fd6c69..65911f00 100644 --- a/src/p2p/p2p.cpp +++ b/src/p2p/p2p.cpp @@ -7,6 +7,8 @@ #include "../hplog.hpp" #include "p2p.hpp" +namespace ssl = boost::asio::ssl; // from + namespace p2p { /** @@ -24,6 +26,11 @@ p2p::peer_session_handler global_peer_session_handler; */ net::io_context ioc; +/** + * SSL context used by the boost library in providing tls support + */ +ssl::context ctx{ssl::context::tlsv13}; + /** * The thread the peer server and client is running on. (not exposed out of this namespace) * Peer connection watchdog runs on this thread. @@ -52,6 +59,7 @@ void start_peer_connections() // Start listening to peers std::make_shared>( ioc, + ctx, tcp::endpoint{address, conf::cfg.peerport}, global_peer_session_handler) ->run(); @@ -76,7 +84,7 @@ void peer_connection_watchdog() if (peer_connections.find(v.first) == peer_connections.end()) { LOG_DBG << "Trying to connect :" << v.second.first << ":" << v.second.second; - std::make_shared>(ioc, global_peer_session_handler) + std::make_shared>(ioc, ctx, global_peer_session_handler) ->run(v.second.first, v.second.second); } } diff --git a/src/p2p/p2p.hpp b/src/p2p/p2p.hpp index 3d5cba28..634ccc50 100644 --- a/src/p2p/p2p.hpp +++ b/src/p2p/p2p.hpp @@ -10,7 +10,7 @@ namespace p2p /** * This is used to store active peer connections mapped by the unique key of socket session */ -extern std::unordered_map *> peer_connections; +extern std::unordered_map< std::string, sock::socket_session *> peer_connections; /** * This is used to store hash of recent peer messages: messagehash -> timestamp of message diff --git a/src/p2p/peer_session_handler.cpp b/src/p2p/peer_session_handler.cpp index a3770f13..c2024a84 100644 --- a/src/p2p/peer_session_handler.cpp +++ b/src/p2p/peer_session_handler.cpp @@ -101,12 +101,12 @@ std::string_view flatbuff_bytes_to_sv(const flatbuffers::Vector *buffer */ void peer_session_handler::on_connect(sock::socket_session *session) { - if (!session->flags_[util::SESSION_FLAG::INBOUND]) + if (!session->flags[util::SESSION_FLAG::INBOUND]) { // We init the session unique id to associate with the challenge. session->init_uniqueid(); peer_connections.insert(std::make_pair(session->uniqueid, session)); - LOG_DBG << "Adding peer to list: " << session->uniqueid << " " << session->address << " " << session->port; + LOG_DBG << "Adding peer to list: " << session->uniqueid; } else { @@ -121,8 +121,6 @@ void peer_session_handler::on_connect(sock::socket_session *session, std::string_view message) { - peer_connections.insert(std::make_pair(session->uniqueid, session)); - //Accessing message buffer const uint8_t *container_pointer = reinterpret_cast(message.data()); size_t container_length = message.length(); diff --git a/src/sock/socket_client.hpp b/src/sock/socket_client.hpp index cd7783b9..664d25e6 100644 --- a/src/sock/socket_client.hpp +++ b/src/sock/socket_client.hpp @@ -1,16 +1,13 @@ #ifndef _SOCK_CLIENT_SESSION_H_ #define _SOCK_CLIENT_SESSION_H_ -#include -#include -#include "socket_session.hpp" #include "socket_session_handler.hpp" #include "../hplog.hpp" namespace beast = boost::beast; namespace net = boost::asio; namespace websocket = boost::beast::websocket; -namespace http = boost::beast::http; +namespace ssl = boost::asio::ssl; using tcp = net::ip::tcp; using error = boost::system::error_code; @@ -24,18 +21,16 @@ namespace sock template class socket_client : public std::enable_shared_from_this> { - tcp::resolver resolver; // resolver used to resolve host and the port - websocket::stream ws; // web socket stream used to send and receive messages - std::string host; // address of the server in which the client connects - std::string port; // port of the server in which client connects - socket_session_handler &sess_handler_; // handler passed to gain access to websocket events + tcp::resolver resolver; // resolver used to resolve host and the port + websocket::stream> ws; // web socket stream used to send and receive messages + std::string host; // address of the server in which the client connects + std::string port; // port of the server in which client connects + socket_session_handler &sess_handler; // handler passed to gain access to websocket events void on_resolve(error ec, tcp::resolver::results_type results); void on_connect(error ec, tcp::resolver::results_type::endpoint_type); - void on_handshake(error ec); - void on_close(error ec); void socket_client_fail(beast::error_code ec, char const *what); @@ -44,15 +39,15 @@ class socket_client : public std::enable_shared_from_this> public: // Resolver and socket require an io_context - socket_client(net::io_context &ioc, socket_session_handler &session_handler); + socket_client(net::io_context &ioc, ssl::context &ctx, socket_session_handler &session_handler); //Entry point to the client which requires an active host and port void run(std::string_view host, std::string_view port); }; template -socket_client::socket_client(net::io_context &ioc, socket_session_handler &session_handler) - : resolver(net::make_strand(ioc)), ws(net::make_strand(ioc)), sess_handler_(session_handler) +socket_client::socket_client(net::io_context &ioc, ssl::context &ctx, socket_session_handler &session_handler) + : resolver(net::make_strand(ioc)), ws(net::make_strand(ioc), ctx), sess_handler(session_handler) { } @@ -99,34 +94,16 @@ template void socket_client::on_connect(error ec, tcp::resolver::results_type::endpoint_type) { if (ec) + { socket_client_fail(ec, "socket_client_connect"); - - // Turn off the timeout on the tcp_stream, because - // the websocket stream has its own timeout system. - beast::get_lowest_layer(ws).expires_never(); - - // Set suggested timeout settings for the websocket - ws.set_option( - websocket::stream_base::timeout::suggested( - beast::role_type::client)); - - // Perform the websocket handshake - ws.async_handshake(host, "/", - [self = this->shared_from_this()](error ec) { - self->on_handshake(ec); - }); -} - -/** - * Executes on completion of handshake -*/ -template -void socket_client::on_handshake(error ec) -{ - //Creates a new socket session object - std::make_shared>( - ws, sess_handler_) - ->client_run(std::move(host), std::move(port), ec); + } + else + { + //Creates a new socket session object + std::make_shared>( + std::move(ws), sess_handler) + ->run(std::move(host), std::move(port), false); + } } /** diff --git a/src/sock/socket_server.hpp b/src/sock/socket_server.hpp index 92b879c1..fff920f1 100644 --- a/src/sock/socket_server.hpp +++ b/src/sock/socket_server.hpp @@ -1,14 +1,12 @@ #ifndef _SOCK_SERVER_LISTENER_H_ #define _SOCK_SERVER_LISTENER_H_ -#include -#include -#include -#include #include "socket_session_handler.hpp" +#include "../conf.hpp" #include "../hplog.hpp" -namespace net = boost::asio; // namespace asio +namespace net = boost::asio; // namespace asio +namespace ssl = boost::asio::ssl; // from using tcp = net::ip::tcp; using error_code = boost::system::error_code; @@ -23,25 +21,25 @@ namespace sock template class socket_server : public std::enable_shared_from_this> { - tcp::acceptor acceptor; // acceptor which accepts new connections - tcp::socket socket; // socket in which the client connects + tcp::acceptor acceptor; // acceptor which accepts new connections + net::io_context &ioc; // socket in which the client connects + ssl::context &ctx; // ssl context which provides support for tls socket_session_handler &sess_handler; // handler passed to gain access to websocket events void fail(error_code ec, char const *what); - void on_accept(error_code ec); + void on_accept(error_code ec, tcp::socket socket); public: - socket_server(net::io_context &ioc, tcp::endpoint endpoint, socket_session_handler &session_handler); + socket_server(net::io_context &ioc, ssl::context &ctx, tcp::endpoint endpoint, socket_session_handler &session_handler); // Start accepting incoming connections void run(); }; - template -socket_server::socket_server(net::io_context &ioc, tcp::endpoint endpoint, socket_session_handler &session_handler) - : acceptor(ioc), socket(ioc), sess_handler(session_handler) +socket_server::socket_server(net::io_context &ioc, ssl::context &ctx, tcp::endpoint endpoint, socket_session_handler &session_handler) + : acceptor(net::make_strand(ioc)), ioc(ioc), ctx(ctx), sess_handler(session_handler) { error_code ec; @@ -85,13 +83,59 @@ socket_server::socket_server(net::io_context &ioc, tcp::endpoint endpoint, so template void socket_server::run() { + // Adding ssl context options disallowing requests which supports sslv2 and sslv3 which have security vulnerabilitis + ctx.set_options( + boost::asio::ssl::context::default_workarounds | + boost::asio::ssl::context::no_sslv2 | + boost::asio::ssl::context::no_sslv3); + + //Providing the certification file for ssl context + ctx.use_certificate_chain_file(conf::ctx.tlsCertFile); + + // Providing key file for the ssl context + ctx.use_private_key_file( + conf::ctx.tlsKeyFile, + boost::asio::ssl::context::pem); // Start accepting a connection acceptor.async_accept( - socket, - [self = this->shared_from_this()](error_code ec) { - self->on_accept(ec); - }); + net::make_strand(ioc), + beast::bind_front_handler( + &socket_server::on_accept, + this->shared_from_this())); +} + +/** + * Executes on acceptance of new connection +*/ +template +void socket_server::on_accept(error_code ec, tcp::socket socket) +{ + if (ec) + { + return fail(ec, "accept"); + } + else + { + + std::string port = std::to_string(socket.remote_endpoint().port()); + std::string address = socket.remote_endpoint().address().to_string(); + + //Creating websocket stream required to pass to initiate a new session + websocket::stream> ws(std::move(socket), ctx); + + // Launch a new session for this connection + std::make_shared>( + std::move(ws), sess_handler) + ->run(std::move(address), std::move(port), true); + } + + // Accept another connection + acceptor.async_accept( + net::make_strand(ioc), + beast::bind_front_handler( + &socket_server::on_accept, + this->shared_from_this())); } /** @@ -106,38 +150,6 @@ void socket_server::fail(error_code ec, char const *what) LOG_ERR << what << ": " << ec.message(); } -/** - * Executes on acceptance of new connection -*/ -template -void socket_server::on_accept(error_code ec) -{ - if (ec) - { - return fail(ec, "accept"); - } - else - { - std::string port = std::to_string(socket.remote_endpoint().port()); - std::string address = socket.remote_endpoint().address().to_string(); - - //Creating websocket stream required to pass to initiate a new session - websocket::stream ws(std::move(socket)); - - // Launch a new session for this connection - std::make_shared>( - ws, sess_handler) - ->server_run(std::move(address), std::move(port)); - } - - // Accept another connection - acceptor.async_accept( - socket, - [self = this->shared_from_this()](error_code ec) { - self->on_accept(ec); - }); -} - } // namespace sock #endif \ No newline at end of file diff --git a/src/sock/socket_session.hpp b/src/sock/socket_session.hpp index 7426a9b2..7fd1f561 100644 --- a/src/sock/socket_session.hpp +++ b/src/sock/socket_session.hpp @@ -8,13 +8,18 @@ #include #include #include -#include "../util.hpp" +#include +#include #include "socket_session_handler.hpp" +#include "../util.hpp" +#include "../hplog.hpp" + namespace beast = boost::beast; namespace net = boost::asio; namespace websocket = boost::beast::websocket; namespace http = boost::beast::http; +namespace ssl = boost::asio::ssl; // from using tcp = net::ip::tcp; using error_code = boost::system::error_code; @@ -46,13 +51,15 @@ class socket_session_handler; template class socket_session : public std::enable_shared_from_this> { - beast::flat_buffer buffer; // used to store incoming messages - websocket::stream ws; // websocket stream used send an recieve messages - std::vector queue; // used to store messages temporarily until it is sent to the relevant party - socket_session_handler &sess_handler; // handler passed to gain access to websocket events + beast::flat_buffer buffer; // used to store incoming messages + websocket::stream> ws; // websocket stream used send an recieve messages + std::vector queue; // used to store messages temporarily until it is sent to the relevant party + socket_session_handler &sess_handler; // handler passed to gain access to websocket events void fail(error_code ec, char const *what); + void on_ssl_handshake(error_code ec); + void on_accept(error_code ec); void on_read(error_code ec, std::size_t bytes_transferred); @@ -62,7 +69,7 @@ class socket_session : public std::enable_shared_from_this> void on_close(error_code ec, std::int8_t type); public: - socket_session(websocket::stream &websocket, socket_session_handler &sess_handler); + socket_session(websocket::stream> websocket, socket_session_handler &sess_handler); ~socket_session(); @@ -82,10 +89,9 @@ public: // The set of util::SESSION_FLAG enum flags that will be set by user-code of this calss. // We mainly use this to store contexual information about this session based on the use case. // Setting and reading flags to this is completely managed by user-code. - std::bitset<8> flags_; + std::bitset<8> flags; - void server_run(const std::string &&address, const std::string &&port); - void client_run(const std::string &&address, const std::string &&port, error_code ec); + void run(const std::string &&address, const std::string &&port, bool is_server_session); void send(T msg); @@ -96,7 +102,7 @@ public: }; template -socket_session::socket_session(websocket::stream &websocket, socket_session_handler &sess_handler) +socket_session::socket_session(websocket::stream> websocket, socket_session_handler &sess_handler) : ws(std::move(websocket)), sess_handler(sess_handler) { // We use binary data instead of ASCII/UTF8 character data. @@ -106,59 +112,81 @@ socket_session::socket_session(websocket::stream &websocke template socket_session::~socket_session() { - sess_handler.on_close(this); + sess_handler.on_close(this); } -//port and address will be used to identify from which client the message recieved in the handler +//port and address will be used to identify from which remote party the message recieved in the handler template -void socket_session::server_run(const std::string &&address, const std::string &&port) +void socket_session::run(const std::string &&address, const std::string &&port, bool is_server_session) { + ssl::stream_base::handshake_type handshake_type = ssl::stream_base::client; + + if (is_server_session) + { + /** + * Set this flag to identify whether this socket session created when node acts as a server + * INBOUND true - when node acts as server + * INBOUND false (OUTBOUND) - when node acts as client + */ + flags.set(util::SESSION_FLAG::INBOUND); + handshake_type = ssl::stream_base::server; + } + this->port = port; this->address = address; - //Set this flag to identify whether this socket session created when node acts as a server - flags_.set(util::SESSION_FLAG::INBOUND); + // Set the timeout. + beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30)); - // Accept the websocket handshake - ws.async_accept( - [sp = this->shared_from_this()]( - error_code ec) { - sp->on_accept(ec); + // Perform the SSL handshake + ws.next_layer().async_handshake( + handshake_type, + [sp = this->shared_from_this()](error_code ec) { + sp->on_ssl_handshake(ec); }); } -//port and address will be used to identify from which server the message recieved in the handler +/* +* Close an active websocket connection gracefully +*/ template -void socket_session::client_run(const std::string &&address, const std::string &&port, error_code ec) +void socket_session::on_ssl_handshake(error_code ec) { - this->port = port; - this->address = address; - if (ec) return fail(ec, "handshake"); - sess_handler.on_connect(this); + // Turn off the timeout on the tcp_stream, because + // the websocket stream has its own timeout system. + beast::get_lowest_layer(ws).expires_never(); - ws.async_read( - buffer, - [sp = this->shared_from_this()]( - error_code ec, std::size_t bytes) { - sp->on_read(ec, bytes); - }); -} + if (flags[util::SESSION_FLAG::INBOUND]) + { + // Set suggested timeout settings for the websocket + ws.set_option( + websocket::stream_base::timeout::suggested( + beast::role_type::server)); -/** - * Executes on error -*/ -template -void socket_session::fail(error_code ec, char const *what) -{ - // LOG_ERR << what << ": " << ec.message(); + // Accept the websocket handshake + ws.async_accept( + [sp = this->shared_from_this()]( + error_code ec) { + sp->on_accept(ec); + }); + } + else + { - // Don't report these - if (ec == net::error::operation_aborted || - ec == websocket::error::closed) - return; + ws.set_option( + websocket::stream_base::timeout::suggested( + beast::role_type::client)); + + // Perform the websocket handshake + ws.async_handshake(this->address, "/", + [sp = this->shared_from_this()]( + error_code ec) { + sp->on_accept(ec); + }); + } } /** @@ -171,7 +199,7 @@ void socket_session::on_accept(error_code ec) if (ec) return fail(ec, "accept"); - sess_handler.on_connect(this); + sess_handler.on_connect(this); // Read a message ws.async_read( @@ -207,7 +235,7 @@ void socket_session::on_read(error_code ec, std::size_t) // read and process the message and we will clear the buffer after its done with it. const char *buffer_data = net::buffer_cast(buffer.data()); std::string_view message(buffer_data, buffer.size()); - sess_handler.on_message(this, message); + sess_handler.on_message(this, message); // Clear the buffer buffer.consume(buffer.size()); @@ -280,10 +308,10 @@ void socket_session::close() { // Close the WebSocket connection ws.async_close(websocket::close_code::normal, - [sp = this->shared_from_this()]( - error_code ec) { - sp->on_close(ec, 0); - }); + [sp = this->shared_from_this()]( + error_code ec) { + sp->on_close(ec, 0); + }); } /* @@ -293,13 +321,11 @@ void socket_session::close() template void socket_session::on_close(error_code ec, std::int8_t type) { - // sess_handler.on_close(this); + if (type == 1) + return; - // if (type == 1) - // return; - - // if (ec) - // return fail(ec, "close"); + if (ec) + return fail(ec, "close"); } // When called, initializes the unique id string for this session. @@ -312,5 +338,19 @@ void socket_session::init_uniqueid() uniqueid.append(address).append(":").append(port); } +/** + * Executes on error +*/ +template +void socket_session::fail(error_code ec, char const *what) +{ + LOG_ERR << what << ": " << ec.message(); + + // Don't report these + if (ec == net::error::operation_aborted || + ec == websocket::error::closed) + return; +} + } // namespace sock #endif diff --git a/src/usr/user_session_handler.cpp b/src/usr/user_session_handler.cpp index 4cdfdd57..72fc3b2d 100644 --- a/src/usr/user_session_handler.cpp +++ b/src/usr/user_session_handler.cpp @@ -54,7 +54,7 @@ void user_session_handler::on_connect(sock::socket_sessionsend(std::move(outmsg)); // Set the challenge-issued flag to help later checks in on_message. - session->flags_.set(util::SESSION_FLAG::USER_CHALLENGE_ISSUED); + session->flags.set(util::SESSION_FLAG::USER_CHALLENGE_ISSUED); } /** @@ -66,7 +66,7 @@ void user_session_handler::on_message( { // First check whether this session is pending challenge. // Meaning we have previously issued a challenge to the client, - if (session->flags_[util::SESSION_FLAG::USER_CHALLENGE_ISSUED]) + if (session->flags[util::SESSION_FLAG::USER_CHALLENGE_ISSUED]) { // The received message must be the challenge response. We need to verify it. auto itr = usr::pending_challenges.find(session->uniqueid); @@ -93,8 +93,8 @@ void user_session_handler::on_message( // All good. Unique public key. // Promote the connection from pending-challenges to authenticated users. - session->flags_.reset(util::SESSION_FLAG::USER_CHALLENGE_ISSUED); // Clear challenge-issued flag - session->flags_.set(util::SESSION_FLAG::USER_AUTHED); // Set the user-authed flag + session->flags.reset(util::SESSION_FLAG::USER_CHALLENGE_ISSUED); // Clear challenge-issued flag + session->flags.set(util::SESSION_FLAG::USER_AUTHED); // Set the user-authed flag usr::add_user(session, userpubkey); // Add the user to the global authed user list usr::pending_challenges.erase(session->uniqueid); // Remove the stored challenge @@ -114,7 +114,7 @@ void user_session_handler::on_message( } } // Check whether this session belongs to an authenticated (challenge-verified) user. - else if (session->flags_[util::SESSION_FLAG::USER_AUTHED]) + else if (session->flags[util::SESSION_FLAG::USER_AUTHED]) { // Check whether this user is among authenticated users // and perform authenticated msg processing. @@ -146,12 +146,12 @@ void user_session_handler::on_close(sock::socket_session // Cleanup any resources related to this session. // Session is awaiting challenge response. - if (session->flags_[util::SESSION_FLAG::USER_CHALLENGE_ISSUED]) + if (session->flags[util::SESSION_FLAG::USER_CHALLENGE_ISSUED]) { usr::pending_challenges.erase(session->uniqueid); } // Session belongs to an authed user. - else if (session->flags_[util::SESSION_FLAG::USER_AUTHED]) + else if (session->flags[util::SESSION_FLAG::USER_AUTHED]) { // Wait for SC process completion before we remove existing user. proc::await_contract_execution(); diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index ec1392dc..2df7446f 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -4,18 +4,21 @@ #include #include #include +#include "usr.hpp" +#include "user_session_handler.hpp" #include "../sock/socket_server.hpp" #include "../sock/socket_session_handler.hpp" #include "../util.hpp" #include "../conf.hpp" #include "../crypto.hpp" #include "../hplog.hpp" -#include "usr.hpp" -#include "user_session_handler.hpp" namespace usr { +// The SSL context is required, and holds certificates +ssl::context ctx{ssl::context::tlsv13}; + /** * Connected (authenticated) user list. (Exposed to other sub systems) * Map key: User socket session id () @@ -249,8 +252,10 @@ int remove_user(const std::string &sessionid) void start_listening() { auto address = net::ip::make_address(conf::cfg.listenip); + std::make_shared>( ioc, + ctx, tcp::endpoint{address, conf::cfg.pubport}, global_usr_session_handler) ->run();