diff --git a/CMakeLists.txt b/CMakeLists.txt index b7cd7d0299b032eeeeedd64f6c53b67ab74ac96b..e6efdb56c1cb7471eb36489364b2ffb803ab4263 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -248,7 +248,7 @@ if (BUILD_TOOLS AND NOT MSVC) tools/dnc/main.cpp tools/dnc/dnc.cpp tools/common.cpp) - target_link_libraries(dnc PRIVATE dhtnet fmt::fmt) + target_link_libraries(dnc PRIVATE dhtnet fmt::fmt yaml-cpp) target_include_directories(dnc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tools) install(TARGETS dnc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) @@ -256,7 +256,7 @@ if (BUILD_TOOLS AND NOT MSVC) tools/dsh/main.cpp tools/dsh/dsh.cpp tools/common.cpp) - target_link_libraries(dsh PRIVATE dhtnet fmt::fmt) + target_link_libraries(dsh PRIVATE dhtnet fmt::fmt yaml-cpp) target_include_directories(dsh PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tools) install(TARGETS dsh RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/tools/common.cpp b/tools/common.cpp index 979274d3549ad82cda67fd704578475aaa29b604..7d338e5b7df98e788f405fa60dce860dc83289ed 100644 --- a/tools/common.cpp +++ b/tools/common.cpp @@ -30,14 +30,10 @@ namespace dhtnet { dht::crypto::Identity -loadIdentity(const std::filesystem::path& path) -{ - if (!std::filesystem::exists(path)) { - std::filesystem::create_directory(path); - } +loadIdentity(const std::filesystem::path& path_id){ try { - for (const auto& path : std::filesystem::directory_iterator(path)) { - auto p = path.path(); + for (const auto& path_id : std::filesystem::directory_iterator(path_id)) { + auto p = path_id.path(); if (p.extension() == ".pem") { auto privateKey = std::make_unique<dht::crypto::PrivateKey>(fileutils::loadFile(p)); auto certificate = std::make_unique<dht::crypto::Certificate>( @@ -45,14 +41,26 @@ loadIdentity(const std::filesystem::path& path) return dht::crypto::Identity(std::move(privateKey), std::move(certificate)); } } - } catch (const std::exception& e) { - fmt::print(stderr, "Error loadind key from .dhtnetTools: {}\n", e.what()); + } catch (const std::exception& e) {} + return {}; +} +dht::crypto::Identity +loadIdentity(const std::filesystem::path& path_id, const std::filesystem::path& path_ca) +{ + if (!std::filesystem::exists(path_id)) { + std::filesystem::create_directory(path_id); } - - auto ca = dht::crypto::generateIdentity("ca"); - auto id = dht::crypto::generateIdentity("dhtnc", ca); + // Load identity + auto id = loadIdentity(path_id); + if (!id.first or !id.second) { + // Load CA + auto ca_id = loadIdentity(path_ca); + if (!ca_id.first or !ca_id.second) + ca_id = dht::crypto::generateIdentity("dhtnet"); + id = dht::crypto::generateIdentity("dhtnet", ca_id); fmt::print("Generated new identity: {}\n", id.first->getPublicKey().getId()); - dht::crypto::saveIdentity(id, path / "id"); + dht::crypto::saveIdentity(id, path_id / "id"); +} return id; } @@ -102,14 +110,13 @@ connectionManagerConfig(const std::filesystem::path& path, config->factory = iceFactory; config->cachePath = path; config->logger = logger; - if (!turn_host.empty()) + if (!turn_host.empty()){ config->turnEnabled = true; - config->turnServer = turn_host; - config->turnServerUserName = turn_user; - config->turnServerPwd = turn_pass; - config->turnServerRealm = turn_realm; - - + config->turnServer = turn_host; + config->turnServerUserName = turn_user; + config->turnServerPwd = turn_pass; + config->turnServerRealm = turn_realm; + } return std::move(config); } template<typename T> diff --git a/tools/common.h b/tools/common.h index 3e143b5b865b481b69e21c959832358d3c667fbf..ea5a2782efa0dfc6bb5e2e2b344616b45b53b3bf 100644 --- a/tools/common.h +++ b/tools/common.h @@ -30,7 +30,7 @@ constexpr size_t BUFFER_SIZE = 64 * 1024; * certification. * @return dht::crypto::Identity */ -dht::crypto::Identity loadIdentity(const std::filesystem::path& path); +dht::crypto::Identity loadIdentity(const std::filesystem::path& path_id, const std::filesystem::path& path_ca); // add certstore to the config std::unique_ptr<ConnectionManager::Config> connectionManagerConfig( const std::filesystem::path& path, diff --git a/tools/dnc/dnc.yaml b/tools/dnc/dnc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6e092fa3a5a0d869c477c348776476cc78ffafe9 --- /dev/null +++ b/tools/dnc/dnc.yaml @@ -0,0 +1,9 @@ +bootstrap: "bootstrap.jami.net" +id_path: HOME/.dhtnet # Change this to the path of the id directory +turn_host: "turn.jami.net" +turn_user: "ring" +turn_pass: "ring" +turn_realm: "ring" +port: 22 +ip: "127.0.0.1" +CA: Home/.dhtnet # Change this to the path of the CA directory diff --git a/tools/dnc/main.cpp b/tools/dnc/main.cpp index f89661e8379836262581ffc3c1c1ad08fd405a05..0ba8b572ce97b20c08f7d4adbbe81e833715487b 100644 --- a/tools/dnc/main.cpp +++ b/tools/dnc/main.cpp @@ -28,6 +28,8 @@ #include <fmt/ostream.h> #endif #include <netinet/in.h> +#include <yaml-cpp/yaml.h> +#include <fstream> struct dhtnc_params { @@ -43,27 +45,32 @@ struct dhtnc_params std::string turn_user {}; std::string turn_pass {}; std::string turn_realm {}; + std::string ca {}; + std::string dnc_configuration {}; }; -static const constexpr struct option long_options[] = {{"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {"port", required_argument, nullptr, 'p'}, - {"ip", required_argument, nullptr, 'i'}, - {"listen", no_argument, nullptr, 'l'}, - {"bootstrap", required_argument, nullptr, 'b'}, - {"id_path", required_argument, nullptr, 'I'}, - {"turn_host", required_argument, nullptr, 't'}, - {"turn_user", required_argument, nullptr, 'u'}, - {"turn_pass", required_argument, nullptr, 'w'}, - {"turn_realm", required_argument, nullptr, 'r'}, - {nullptr, 0, nullptr, 0}}; +static const constexpr struct option long_options[] + = {{"help", no_argument, nullptr, 'h'}, + {"version", no_argument, nullptr, 'v'}, + {"port", required_argument, nullptr, 'p'}, + {"ip", required_argument, nullptr, 'i'}, + {"listen", no_argument, nullptr, 'l'}, + {"bootstrap", required_argument, nullptr, 'b'}, + {"id_path", required_argument, nullptr, 'I'}, + {"turn_host", required_argument, nullptr, 't'}, + {"turn_user", required_argument, nullptr, 'u'}, + {"turn_pass", required_argument, nullptr, 'w'}, + {"turn_realm", required_argument, nullptr, 'r'}, + {"CA", required_argument, nullptr, 'C'}, + {"dnc_configuration", required_argument, nullptr, 'd'}, + {nullptr, 0, nullptr, 0}}; dhtnc_params parse_args(int argc, char** argv) { dhtnc_params params; int opt; - while ((opt = getopt_long(argc, argv, "hvlw:r:u:t:I:b:p:i:", long_options, nullptr)) != -1) { + while ((opt = getopt_long(argc, argv, "hvlw:r:u:t:I:b:p:i:C:d:", long_options, nullptr)) != -1) { switch (opt) { case 'h': params.help = true; @@ -98,6 +105,11 @@ parse_args(int argc, char** argv) case 'r': params.turn_realm = optarg; break; + case 'C': + params.ca = optarg; + break; + case 'd': + params.dnc_configuration = optarg; default: std::cerr << "Invalid option" << std::endl; exit(EXIT_FAILURE); @@ -115,23 +127,43 @@ parse_args(int argc, char** argv) } } - // default values - if (params.remote_port == 0) - params.remote_port = 22; - if (params.remote_host.empty()) - params.remote_host = "127.0.0.1"; - if (params.bootstrap.empty()) - params.bootstrap = "bootstrap.jami.net"; - if (params.path.empty()) - params.path = std::filesystem::path(getenv("HOME")) / ".dhtnet"; - if (params.turn_host.empty()) - params.turn_host = "turn.jami.net"; - if (params.turn_user.empty()) - params.turn_user = "ring"; - if (params.turn_pass.empty()) - params.turn_pass = "ring"; - if (params.turn_realm.empty()) - params.turn_realm = "ring"; + // extract values from dnc yaml file + if (!params.dnc_configuration.empty()) { + printf("read configuration file: %s\n", params.dnc_configuration.c_str()); + std::ifstream config_file(params.dnc_configuration); + if (!config_file.is_open()) { + std::cerr << "Error: Could not open configuration file.\n"; + } else { + YAML::Node config = YAML::Load(config_file); + if (config["bootstrap"] && params.bootstrap.empty()) { + params.bootstrap = config["bootstrap"].as<std::string>(); + } + if (config["id_path"] && params.path.empty()) { + params.path = config["id_path"].as<std::string>(); + } + if (config["turn_host"] && params.turn_host.empty()) { + params.turn_host = config["turn_host"].as<std::string>(); + } + if (config["turn_user"] && params.turn_user.empty()) { + params.turn_user = config["turn_user"].as<std::string>(); + } + if (config["turn_pass"] && params.turn_pass.empty()) { + params.turn_pass = config["turn_pass"].as<std::string>(); + } + if (config["turn_realm"] && params.turn_realm.empty()) { + params.turn_realm = config["turn_realm"].as<std::string>(); + } + if (config["CA"] && params.ca.empty()) { + params.ca = config["CA"].as<std::string>(); + } + if (config["ip"] && params.remote_host.empty()) { + params.dnc_configuration = config["ip"].as<std::string>(); + } + if (config["port"] && params.remote_port == 0) { + params.remote_port = config["port"].as<int>(); + } + } + } return params; } @@ -156,20 +188,21 @@ main(int argc, char** argv) setSipLogLevel(); auto params = parse_args(argc, argv); - if (params.help ){ - fmt::print("Usage: dnc [options] [PEER_ID]\n" - "\nOptions:\n" - " -h, --help Show this help message and exit.\n" - " -v, --version Display the program version.\n" - " -p, --port Specify the port option with an argument.\n" - " -i, --ip Specify the ip option with an argument.\n" - " -l, --listen Start the program in listen mode.\n" - " -b, --bootstrap Specify the bootstrap option with an argument.\n" - " -I, --id_path Specify the id_path option with an argument.\n" - " -t, --turn_host Specify the turn_host option with an argument.\n" - " -u, --turn_user Specify the turn_user option with an argument.\n" - " -w, --turn_pass Specify the turn_pass option with an argument.\n" - " -r, --turn_realm Specify the turn_realm option with an argument.\n"); + if (params.help) { + fmt::print("Usage: dnc [options] [PEER_ID]\n" + "\nOptions:\n" + " -h, --help Show this help message and exit.\n" + " -v, --version Display the program version.\n" + " -p, --port Specify the port option with an argument.\n" + " -i, --ip Specify the ip option with an argument.\n" + " -l, --listen Start the program in listen mode.\n" + " -b, --bootstrap Specify the bootstrap option with an argument.\n" + " -I, --id_path Specify the id_path option with an argument.\n" + " -t, --turn_host Specify the turn_host option with an argument.\n" + " -u, --turn_user Specify the turn_user option with an argument.\n" + " -w, --turn_pass Specify the turn_pass option with an argument.\n" + " -r, --turn_realm Specify the turn_realm option with an argument.\n" + " -C, --CA Specify the CA option with an argument.\n"); return EXIT_SUCCESS; } if (params.version) { @@ -178,13 +211,19 @@ main(int argc, char** argv) } fmt::print("dnc 1.0\n"); - auto identity = dhtnet::loadIdentity(params.path); + auto identity = dhtnet::loadIdentity(params.path, params.ca); fmt::print("Loaded identity: {} from {}\n", identity.second->getId(), params.path); std::unique_ptr<dhtnet::Dnc> dhtnc; if (params.listen) { // create dnc instance - dhtnc = std::make_unique<dhtnet::Dnc>(params.path, identity, params.bootstrap, params.turn_host, params.turn_user, params.turn_pass, params.turn_realm); + dhtnc = std::make_unique<dhtnet::Dnc>(params.path, + identity, + params.bootstrap, + params.turn_host, + params.turn_user, + params.turn_pass, + params.turn_realm); } else { dhtnc = std::make_unique<dhtnet::Dnc>(params.path, identity, @@ -195,8 +234,7 @@ main(int argc, char** argv) params.turn_host, params.turn_user, params.turn_pass, - params.turn_realm - ); + params.turn_realm); } dhtnc->run(); return EXIT_SUCCESS; diff --git a/tools/dsh/dsh.yaml b/tools/dsh/dsh.yaml new file mode 100644 index 0000000000000000000000000000000000000000..54e13abb7252b4ae0745ddcbbebaf612bc70828d --- /dev/null +++ b/tools/dsh/dsh.yaml @@ -0,0 +1,8 @@ +bootstrap: "bootstrap.jami.net" +id_path: HOME/.dhtnet # Change this to the path of the id directory +turn_host: "turn.jami.net" +turn_user: "ring" +turn_pass: "ring" +turn_realm: "ring" +binary: "bash" +CA: HOME/.dhtnet # Change this to the path of the CA directory diff --git a/tools/dsh/main.cpp b/tools/dsh/main.cpp index b6697a3842d0f9e12392b729e2297f207cd079ce..7c5e006a6dbf8cdd2dc01caab4006a65d93f93c9 100644 --- a/tools/dsh/main.cpp +++ b/tools/dsh/main.cpp @@ -122,13 +122,40 @@ parse_args(int argc, char** argv) } } - // default values - if (params.bootstrap.empty()) - params.bootstrap = "bootstrap.jami.net"; - if (params.binary.empty()) - params.binary = "bash"; - if (params.path.empty()) - params.path = std::filesystem::path(getenv("HOME")) / ".dhtnet"; + // extract values from dsh yaml file + if (!params.dsh_configuration.empty()) { + printf("read configuration file: %s\n", params.dsh_configuration.c_str()); + std::ifstream config_file(params.dsh_configuration); + if (!config_file.is_open()) { + std::cerr << "Error: Could not open configuration file.\n"; + } else { + YAML::Node config = YAML::Load(config_file); + if (config["bootstrap"] && params.bootstrap.empty()) { + params.bootstrap = config["bootstrap"].as<std::string>(); + } + if (config["id_path"] && params.path.empty()) { + params.path = config["id_path"].as<std::string>(); + } + if (config["turn_host"] && params.turn_host.empty()) { + params.turn_host = config["turn_host"].as<std::string>(); + } + if (config["turn_user"] && params.turn_user.empty()) { + params.turn_user = config["turn_user"].as<std::string>(); + } + if (config["turn_pass"] && params.turn_pass.empty()) { + params.turn_pass = config["turn_pass"].as<std::string>(); + } + if (config["turn_realm"] && params.turn_realm.empty()) { + params.turn_realm = config["turn_realm"].as<std::string>(); + } + if (config["CA"] && params.ca.empty()) { + params.ca = config["CA"].as<std::string>(); + } + if (config["binary"] && params.binary.empty()) { + params.binary = config["binary"].as<std::string>(); + } + } + } return params; } @@ -179,7 +206,7 @@ main(int argc, char** argv) fmt::print("dsh 1.0\n"); - auto identity = dhtnet::loadIdentity(params.path); + auto identity = dhtnet::loadIdentity(params.path, params.ca); fmt::print("Loaded identity: {} from {}\n", identity.second->getId(), params.path); std::unique_ptr<dhtnet::Dsh> dhtsh; diff --git a/tools/dvpn/dvpn.yaml b/tools/dvpn/dvpn.yaml new file mode 100644 index 0000000000000000000000000000000000000000..20929ecd27f4c3e31f7da5efea58c03c40a6e6b9 --- /dev/null +++ b/tools/dvpn/dvpn.yaml @@ -0,0 +1,9 @@ +bootstrap: "bootstrap.jami.net" +id_path: HOME/.dhtnet # Change this to the path of the id directory +turn_host: "turn.jami.net" +turn_user: "ring" +turn_pass: "ring" +turn_realm: "ring" +configuration_file: "./test_config.yaml" +CA: HOME/.dhtnet # Change this to the path of the CA directory + diff --git a/tools/dvpn/main.cpp b/tools/dvpn/main.cpp index 66f8e139de1e86be16749aa5dcc658c4378eda2b..97dd0de06d757114be672282f29ac9aaf6bada05 100644 --- a/tools/dvpn/main.cpp +++ b/tools/dvpn/main.cpp @@ -28,6 +28,8 @@ #include <fmt/ostream.h> #endif #include <netinet/in.h> +#include <yaml-cpp/yaml.h> +#include <fstream> struct dhtvpn_params { @@ -42,6 +44,8 @@ struct dhtvpn_params std::string turn_pass {}; std::string turn_realm {}; std::string configuration_file {}; + std::string ca {}; + std::string dvpn_configuration_file {}; }; static const constexpr struct option long_options[] @@ -54,7 +58,9 @@ static const constexpr struct option long_options[] {"turn_user", required_argument, nullptr, 'u'}, {"turn_pass", required_argument, nullptr, 'w'}, {"turn_realm", required_argument, nullptr, 'r'}, - {"configuration_file", required_argument, nullptr, 'c'}, + {"vpn_configuration_file", required_argument, nullptr, 'c'}, + {"CA", required_argument, nullptr, 'C'}, + {"dvpn_configuration_file", required_argument, nullptr, 'd'}, {nullptr, 0, nullptr, 0}}; dhtvpn_params @@ -62,7 +68,7 @@ parse_args(int argc, char** argv) { dhtvpn_params params; int opt; - while ((opt = getopt_long(argc, argv, "hvlw:r:u:t:I:b:c:", long_options, nullptr)) != -1) { + while ((opt = getopt_long(argc, argv, "hvlw:r:u:t:I:b:c:C:d:", long_options, nullptr)) != -1) { switch (opt) { case 'h': params.help = true; @@ -94,11 +100,51 @@ parse_args(int argc, char** argv) case 'c': params.configuration_file = optarg; break; + case 'C': + params.ca = optarg; + break; + case 'd': + params.dvpn_configuration_file = optarg; + break; default: std::cerr << "Invalid option" << std::endl; exit(EXIT_FAILURE); } } + // extract values from dvpn yaml file + if (!params.dvpn_configuration_file.empty()) { + printf("read configuration file: %s\n", params.dvpn_configuration_file.c_str()); + std::ifstream config_file(params.dvpn_configuration_file); + if (!config_file.is_open()) { + std::cerr << "Error: Could not open configuration file.\n"; + } else { + YAML::Node config = YAML::Load(config_file); + if (config["bootstrap"] && params.bootstrap.empty()) { + params.bootstrap = config["bootstrap"].as<std::string>(); + } + if (config["id_path"] && params.path.empty()) { + params.path = config["id_path"].as<std::string>(); + } + if (config["turn_host"] && params.turn_host.empty()) { + params.turn_host = config["turn_host"].as<std::string>(); + } + if (config["turn_user"] && params.turn_user.empty()) { + params.turn_user = config["turn_user"].as<std::string>(); + } + if (config["turn_pass"] && params.turn_pass.empty()) { + params.turn_pass = config["turn_pass"].as<std::string>(); + } + if (config["turn_realm"] && params.turn_realm.empty()) { + params.turn_realm = config["turn_realm"].as<std::string>(); + } + if (config["CA"] && params.ca.empty()) { + params.ca = config["CA"].as<std::string>(); + } + if (config["configuration_file"] && params.configuration_file.empty()) { + params.configuration_file = config["configuration_file"].as<std::string>(); + } + } + } // If not listening, the peer_id argument is required if (!params.listen && !params.help && !params.version) { @@ -110,24 +156,6 @@ parse_args(int argc, char** argv) exit(EXIT_FAILURE); } } - - // default values - - if (params.bootstrap.empty()) - params.bootstrap = "bootstrap.jami.net"; - if (params.path.empty()) - params.path = std::filesystem::path(getenv("HOME")) / ".dhtnet"; - if (params.turn_host.empty()) - params.turn_host = "turn.jami.net"; - if (params.turn_user.empty()) - params.turn_user = "ring"; - if (params.turn_pass.empty()) - params.turn_pass = "ring"; - if (params.turn_realm.empty()) - params.turn_realm = "ring"; - if (params.configuration_file.empty()) - params.configuration_file = std::filesystem::path(__FILE__).parent_path()/"test_config.yaml"; - return params; } @@ -165,7 +193,9 @@ main(int argc, char** argv) " -u, --turn_user Specify the turn_user option with an argument.\n" " -w, --turn_pass Specify the turn_pass option with an argument.\n" " -r, --turn_realm Specify the turn_realm option with an argument.\n" - " -c, --configuration_file Specify the configuration_file path option with an argument.\n" + " -c, --vpn_configuration_file Specify the vpn_configuration_file path option with an argument.\n" + " -C, --CA Specify the CA path option with an argument.\n" + " -d, --dvpn_configuration_file Specify the dvpn_configuration_file path option with an argument.\n" "\n"); return EXIT_SUCCESS; } @@ -175,7 +205,8 @@ main(int argc, char** argv) } fmt::print("dvpn 1.0\n"); - auto identity = dhtnet::loadIdentity(params.path); + + auto identity = dhtnet::loadIdentity(params.path, params.ca); fmt::print("Loaded identity: {} from {}\n", identity.second->getId(), params.path); std::unique_ptr<dhtnet::Dvpn> dvpn;