aboutsummaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-10-21 14:01:26 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2016-10-21 18:15:46 +0200
commit510ce3bec7915a790fbf75ace5521e437d9d416a (patch)
tree7b9286875652b677a110287d11d024f85879cc7a /node
parent640e0ad7a762d0473581c2114c2c945961bea80f (diff)
downloadcmix-510ce3bec7915a790fbf75ace5521e437d9d416a.tar.gz
cmix-510ce3bec7915a790fbf75ace5521e437d9d416a.tar.bz2
cmix-510ce3bec7915a790fbf75ace5521e437d9d416a.zip
Adds SSL connections between nodes.
Diffstat (limited to 'node')
-rw-r--r--node/main.cpp67
-rw-r--r--node/node.cpp41
-rw-r--r--node/node.hpp15
3 files changed, 100 insertions, 23 deletions
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 <boost/program_options.hpp>
+#include <boost/filesystem/operations.hpp>
#include <iostream>
@@ -18,8 +19,12 @@ int main(int argc, char* argv[]) {
("interface4,4", po::value<std::string>()->default_value("0.0.0.0"), "Set the ipv4 address to listen on.")
("enable_v6", po::value<bool>()->default_value(true), "Enable/disable ipv6 accept support.")
("interface6,6", po::value<std::string>()->default_value("::"), "Set the ipv6 address to listen on.")
- ("next_node,n", po::value<std::string>(), "The address of the next node in the network")
+ ("next_node,n", po::value<std::string>(), "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<std::string>(), "The cert file to use (in pem format).")
+ ("key,k", po::value<std::string>(), "The key file (in pem format).")
+ ("dhparam,d", po::value<std::string>(), "The dhparam file.")
+ ("certdir", po::value<std::string>(), "Directory containing trusted certificates.")
;
po::variables_map vm;
@@ -37,12 +42,54 @@ int main(int argc, char* argv[]) {
std::string if6 = vm["interface6"].as<std::string>();
uint16_t port = vm["port"].as<uint16_t>();
- 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<std::string>();
+ 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<std::string>();
+ 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<std::string>();
+ 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<std::string>();
+ 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>(boost::asio::ssl::context::sslv23))
+, server(io_service, listen_settings, ctx, [this](std::unique_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>&& socket, std::shared_ptr<boost::asio::ssl::context> 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<boost::asio::ssl::stream<tcp::socket>>(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(io_service, *ctx))))
+, next_node(SSLSender(std::unique_ptr<boost::asio::ssl::stream<tcp::socket>>(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(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<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>&& socket, std::shared_ptr<boost::asio::ssl::context> ctx)
{
- std::list<Receiver>::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<boost::asio::ssl::context> ctx;
Server server;
- typedef std::list<Receiver> Purgatory;
+ typedef std::list<SSLReceiver> Purgatory;
Purgatory purgatory;
- typedef std::map<std::string, SenderReceiver> ClientConnections;
+ typedef std::map<std::string, SSLSenderReceiver> ClientConnections;
ClientConnections clients;
typedef std::map<std::string, CMixClientData> ClientData;
ClientData data;
NodeNetworkSettings network_settings;
- Receiver prev_node;
- Sender next_node;
+ SSLReceiver prev_node;
+ SSLSender next_node;
Api api;
KeyPair keypair;
std::vector<uint8_t> network_key;
bool shutting_down;
-
- void accept_handler(boost::asio::ip::tcp::socket&& socket);
+ void accept_handler(std::unique_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>&& socket, std::shared_ptr<boost::asio::ssl::context> ctx);
+
+ void connect_to_next_node();
void start_precomputation();
void start_initialisation();