From 510ce3bec7915a790fbf75ace5521e437d9d416a Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Fri, 21 Oct 2016 14:01:26 +0200 Subject: Adds SSL connections between nodes. --- node/main.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- node/node.cpp | 41 +++++++++++++++++++++++++----------- node/node.hpp | 15 +++++++------ 3 files changed, 100 insertions(+), 23 deletions(-) (limited to 'node') diff --git a/node/main.cpp b/node/main.cpp index 527e3c5..0c81312 100644 --- a/node/main.cpp +++ b/node/main.cpp @@ -4,6 +4,7 @@ #include "logging.hpp" #include +#include #include @@ -18,8 +19,12 @@ int main(int argc, char* argv[]) { ("interface4,4", po::value()->default_value("0.0.0.0"), "Set the ipv4 address to listen on.") ("enable_v6", po::value()->default_value(true), "Enable/disable ipv6 accept support.") ("interface6,6", po::value()->default_value("::"), "Set the ipv6 address to listen on.") - ("next_node,n", po::value(), "The address of the next node in the network") + ("next_node,n", po::value(), "The address of the next node in the network.") ("first,f", "This is the first node and will be the communication point for the clients.") + ("cert,c", po::value(), "The cert file to use (in pem format).") + ("key,k", po::value(), "The key file (in pem format).") + ("dhparam,d", po::value(), "The dhparam file.") + ("certdir", po::value(), "Directory containing trusted certificates.") ; po::variables_map vm; @@ -37,12 +42,54 @@ int main(int argc, char* argv[]) { std::string if6 = vm["interface6"].as(); uint16_t port = vm["port"].as(); - init_logging(boost::log::trivial::severity_level::trace, "node_" + std::to_string(port)); + std::string cert; + if(vm.count("cert")) { + std::string filename = vm["cert"].as(); + if(boost::filesystem::exists(filename)) { + cert = filename; + } else { + std::cerr << "cert file: \"" << filename << "\" does not exist"; + return -1; + } + } else { + std::cerr << "supplying a certificate is required" << std::endl; + return -1; + } - BOOST_LOG_TRIVIAL(info) << "Started node"; + std::string key; + if(vm.count("key")) { + std::string filename = vm["key"].as(); + if(boost::filesystem::exists(filename)) { + key = filename; + } else { + std::cerr << "key file: \"" << filename << "\" does not exist"; + return -1; + } + } else { + std::cerr << "supplying a key file is required" << std::endl; + return -1; + } + + std::string dhparam; + if(vm.count("dhparam")) { + std::string filename = vm["dhparam"].as(); + if(boost::filesystem::exists(filename)) { + dhparam = filename; + } else { + std::cerr << "dhparam file: \"" << filename << "\" does not exist"; + return -1; + } + } else { + std::cerr << "supplying a dhparam file is required" << std::endl; + return -1; + } + + ListenSettings lsettings{en4, if4, en6, if6, port, true, cert, key, dhparam}; - ListenSettings lsettings{en4, if4, en6, if6, port}; + init_logging(boost::log::trivial::severity_level::trace, "node_" + std::to_string(port)); + + BOOST_LOG_TRIVIAL(info) << "Started node"; bool is_first = bool(vm.count("first")); std::string next_node; @@ -52,10 +99,20 @@ int main(int argc, char* argv[]) { std::cerr << "next_node option is required." << std::endl; return -1; } + std::string certdir; + if(vm.count("certdir")) { + std::string filename = vm["certdir"].as(); + if(boost::filesystem::is_directory(filename)) { + certdir = filename; + } else { + std::cerr << "cert dir: \"" << filename << "\" is not a directory"; + return -1; + } + } Uri uri = parse_uri(next_node); - NodeNetworkSettings nsettings{is_first, uri.host, uri.port}; + NodeNetworkSettings nsettings{is_first, uri.host, uri.port, certdir}; Node node(lsettings, nsettings); node.run(); diff --git a/node/node.cpp b/node/node.cpp index 04ed4f1..2dfbba8 100644 --- a/node/node.cpp +++ b/node/node.cpp @@ -11,12 +11,13 @@ using namespace boost::asio::ip; Node::Node(ListenSettings const& listen_settings, NodeNetworkSettings network_settings) : io_service() -, server(io_service, listen_settings, [this](boost::asio::ip::tcp::socket&& socket){accept_handler(std::move(socket));}) +, ctx(std::make_shared(boost::asio::ssl::context::sslv23)) +, server(io_service, listen_settings, ctx, [this](std::unique_ptr>&& socket, std::shared_ptr ctx){accept_handler(std::move(socket), ctx);}) , clients() , data() , network_settings(network_settings) -, prev_node(Receiver(tcp::socket(io_service))) -, next_node(Sender(tcp::socket(io_service))) +, prev_node(SSLReceiver(std::unique_ptr>(new boost::asio::ssl::stream(io_service, *ctx)))) +, next_node(SSLSender(std::unique_ptr>(new boost::asio::ssl::stream(io_service, *ctx)))) , api(get_implementation()) , keypair(api.create_key_pair()) , network_key() @@ -24,11 +25,9 @@ Node::Node(ListenSettings const& listen_settings, NodeNetworkSettings network_se { GOOGLE_PROTOBUF_VERIFY_VERSION; - auto on_connect = [this, network_settings](){ - next_node.async_send(cmix_proto::ImANode()); - }; - - next_node.async_connect(network_settings.next_host, network_settings.next_port, on_connect); + if(network_settings.is_first) { + connect_to_next_node(); + } } Node::~Node() { @@ -39,9 +38,9 @@ void Node::run() { io_service.run(); } -void Node::accept_handler(boost::asio::ip::tcp::socket&& socket) +void Node::accept_handler(std::unique_ptr>&& socket, std::shared_ptr ctx) { - std::list::iterator it = purgatory.emplace(purgatory.end(), std::move(socket)); + Purgatory::iterator it = purgatory.emplace(purgatory.end(), std::move(socket)); purgatory.back().on_done( [this, it]() { purgatory.erase(it); @@ -53,6 +52,20 @@ void Node::accept_handler(boost::asio::ip::tcp::socket&& socket) }); } +void Node::connect_to_next_node() +{ + if(!network_settings.certdir.empty()) { + ctx->add_verify_path(network_settings.certdir); + } + + auto on_connect = [this](){ + BOOST_LOG_TRIVIAL(trace) << "Connected to next_node"; + next_node.async_send(cmix_proto::ImANode()); + }; + + next_node.async_connect(network_settings.next_host, network_settings.next_port, on_connect); +} + void Node::start_initialisation() { cmix_proto::Initialization init; init.set_public_share(keypair.pub, keypair.pub_len); @@ -105,6 +118,8 @@ void Node::handle_node_secretkey(cmix_proto::SecretKey const& secret) if(network_settings.is_first) { start_precomputation(); + } else { + next_node.async_send(secret); } } @@ -173,11 +188,13 @@ void Node::handle_client_message(ClientConnections::key_type handle, cmix_proto: void Node::handle_imanode(Purgatory::iterator handle) { handle->on_done([]{}); - prev_node = Receiver(std::move(*handle)); + prev_node = SSLReceiver(std::move(*handle)); purgatory.erase(handle); if(network_settings.is_first) { start_initialisation(); + } else { + connect_to_next_node(); } prev_node.async_receive([this](cmix_proto::CMixMessage message){ @@ -187,7 +204,7 @@ void Node::handle_imanode(Purgatory::iterator handle) { void Node::handle_imaclient(Purgatory::iterator handle, cmix_proto::ImAClient c) { std::string client_id = c.id(); - clients.emplace(c.id(), SenderReceiver(std::move(*handle))); + clients.emplace(c.id(), SSLSenderReceiver(std::move(*handle))); clients.at(c.id()).on_done([this, client_id]{ clients.erase(client_id); }); diff --git a/node/node.hpp b/node/node.hpp index ac379ca..9d59687 100644 --- a/node/node.hpp +++ b/node/node.hpp @@ -24,6 +24,7 @@ struct NodeNetworkSettings { bool is_first; ///< Are we the first node in the network. std::string next_host; ///< Next nodes host. std::string next_port; ///< Next nodes port. + std::string certdir; ///< Directory containing trusted certificate authorities. }; /*! @@ -36,29 +37,31 @@ class Node }; boost::asio::io_service io_service; + std::shared_ptr ctx; Server server; - typedef std::list Purgatory; + typedef std::list Purgatory; Purgatory purgatory; - typedef std::map ClientConnections; + typedef std::map ClientConnections; ClientConnections clients; typedef std::map ClientData; ClientData data; NodeNetworkSettings network_settings; - Receiver prev_node; - Sender next_node; + SSLReceiver prev_node; + SSLSender next_node; Api api; KeyPair keypair; std::vector network_key; bool shutting_down; - - void accept_handler(boost::asio::ip::tcp::socket&& socket); + void accept_handler(std::unique_ptr>&& socket, std::shared_ptr ctx); + + void connect_to_next_node(); void start_precomputation(); void start_initialisation(); -- cgit v1.2.3-70-g09d2