diff --git a/CMakeLists.txt b/CMakeLists.txt index e6efdb56c1cb7471eb36489364b2ffb803ab4263..7b1b1e309564da1812fde9274f21a96fd3440551 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -247,7 +247,8 @@ if (BUILD_TOOLS AND NOT MSVC) add_executable(dnc tools/dnc/main.cpp tools/dnc/dnc.cpp - tools/common.cpp) + tools/common.cpp + tools/dhtnet_crtmgr/dhtnet_crtmgr.cpp) 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}) @@ -255,7 +256,8 @@ if (BUILD_TOOLS AND NOT MSVC) add_executable(dsh tools/dsh/main.cpp tools/dsh/dsh.cpp - tools/common.cpp) + tools/common.cpp + tools/dhtnet_crtmgr/dhtnet_crtmgr.cpp) 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}) @@ -263,7 +265,8 @@ if (BUILD_TOOLS AND NOT MSVC) add_executable(dvpn tools/dvpn/main.cpp tools/dvpn/dvpn.cpp - tools/common.cpp) + tools/common.cpp + tools/dhtnet_crtmgr/dhtnet_crtmgr.cpp) target_link_libraries(dvpn PRIVATE dhtnet fmt::fmt yaml-cpp) target_include_directories(dvpn PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tools) install(TARGETS dvpn RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) @@ -280,6 +283,13 @@ if (BUILD_TOOLS AND NOT MSVC) target_include_directories(upnpctrl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tools) install(TARGETS upnpctrl RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + add_executable(dhtnet-crtmgr + tools/dhtnet_crtmgr/main.cpp + tools/dhtnet_crtmgr/dhtnet_crtmgr.cpp) + target_link_libraries(dhtnet-crtmgr PRIVATE dhtnet fmt::fmt) + target_include_directories(dhtnet-crtmgr PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tools) + install(TARGETS dhtnet-crtmgr RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + install(FILES tools/dnc/dnc.1 tools/dsh/dsh.1 diff --git a/tools/common.cpp b/tools/common.cpp index 7d338e5b7df98e788f405fa60dce860dc83289ed..76597a824d0655043b761eac81c9dd66ccb42130 100644 --- a/tools/common.cpp +++ b/tools/common.cpp @@ -29,41 +29,6 @@ namespace dhtnet { -dht::crypto::Identity -loadIdentity(const std::filesystem::path& path_id){ - try { - 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>( - fileutils::loadFile(p.replace_extension(".crt"))); - return dht::crypto::Identity(std::move(privateKey), std::move(certificate)); - } - } - } 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); - } - // 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 / "id"); -} - return id; -} - std::unique_ptr<ConnectionManager::Config> connectionManagerConfig(const std::filesystem::path& path, dht::crypto::Identity identity, diff --git a/tools/common.h b/tools/common.h index ea5a2782efa0dfc6bb5e2e2b344616b45b53b3bf..67672d08bf62036ee063a9768bec57957e273b2f 100644 --- a/tools/common.h +++ b/tools/common.h @@ -25,13 +25,6 @@ namespace dhtnet { using Buffer = std::shared_ptr<std::vector<uint8_t>>; constexpr size_t BUFFER_SIZE = 64 * 1024; -/** - * Attempt to retrieve the identity from the .ssh directory, and if none is found, generate a new - * certification. - * @return dht::crypto::Identity - */ -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, dht::crypto::Identity identity, diff --git a/tools/dhtnet_crtmgr/dhtnet_crtmgr.cpp b/tools/dhtnet_crtmgr/dhtnet_crtmgr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d3d94a77399e191862cdac9b2cdba67e3d14ca4 --- /dev/null +++ b/tools/dhtnet_crtmgr/dhtnet_crtmgr.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2023 Savoir-faire Linux Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "dhtnet_crtmgr.h" +#include "fileutils.h" + +#include <opendht/crypto.h> + + +namespace dhtnet { + +dht::crypto::Identity +loadIdentity(const std::filesystem::path& privatekey, const std::filesystem::path& cert) +{ + // check files exists + if (!std::filesystem::exists(privatekey) or !std::filesystem::exists(cert)) + { + fmt::print(stderr, "Error: missing identity files\n"); + return {}; + } + + // Load identity + auto privateKey = std::make_unique<dht::crypto::PrivateKey>(fileutils::loadFile(privatekey)); + auto certificate = std::make_unique<dht::crypto::Certificate>(fileutils::loadFile(cert)); + return dht::crypto::Identity(std::move(privateKey), std::move(certificate)); +} + +// generate a new identity +dht::crypto::Identity generateIdentity(const std::filesystem::path& path_id, const std::string& name, const dht::crypto::Identity& ca) +{ + auto identity = dht::crypto::generateIdentity(name, ca); + if (!std::filesystem::exists(path_id)) + std::filesystem::create_directories(path_id); + dht::crypto::saveIdentity(identity, path_id / name); + return identity; +} +} // namespace dhtnet diff --git a/tools/dhtnet_crtmgr/dhtnet_crtmgr.h b/tools/dhtnet_crtmgr/dhtnet_crtmgr.h new file mode 100644 index 0000000000000000000000000000000000000000..16fe9e9c6f1144b97b02b607586463be54c1947f --- /dev/null +++ b/tools/dhtnet_crtmgr/dhtnet_crtmgr.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 Savoir-faire Linux Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +#include <opendht/crypto.h> +#include "fileutils.h" + +namespace dhtnet { + +/** + * Get the private key and certificate from the given paths. + * @return dht::crypto::Identity + */ +dht::crypto::Identity loadIdentity(const std::filesystem::path& path_pkey, const std::filesystem::path& path_cert); + +/** + * Generate a new identity. + */ +dht::crypto::Identity generateIdentity(const std::filesystem::path& path_id, const std::string& name, const dht::crypto::Identity& ca = {}); + +} \ No newline at end of file diff --git a/tools/dhtnet_crtmgr/main.cpp b/tools/dhtnet_crtmgr/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f27d5bba70486a20b8b3929a972eaf91668095ea --- /dev/null +++ b/tools/dhtnet_crtmgr/main.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2023 Savoir-faire Linux Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +#include "dhtnet_crtmgr.h" + + +#include <iostream> +#include <unistd.h> +#include <getopt.h> +#if __has_include(<fmt/std.h>) +#include <fmt/std.h> +#else +#include <fmt/ostream.h> +#endif + + +struct dhtnet_crtmgr_params +{ + bool help {false}; + bool version {false}; + std::filesystem::path ca {}; + std::filesystem::path id {}; + std::filesystem::path privatekey {}; + bool pkid {false}; + std::string name {}; + bool setup {false}; +}; +static const constexpr struct option long_options[] + = {{"help", no_argument, nullptr, 'h'}, + {"version", no_argument, nullptr, 'v'}, + {"CA", required_argument, nullptr, 'c'}, + {"id", required_argument, nullptr, 'i'}, + {"privatekey", required_argument, nullptr, 'p'}, + {"name", required_argument, nullptr, 'n'}, + {"pkid", no_argument, nullptr, 'g'}, + {"setup", no_argument, nullptr, 's'}, + {nullptr, 0, nullptr, 0}}; + +dhtnet_crtmgr_params +parse_args(int argc, char** argv) +{ + dhtnet_crtmgr_params params; + int opt; + while ((opt = getopt_long(argc, argv, "hgsv:c:i:p:n:", long_options, nullptr)) != -1) { + switch (opt) { + case 'h': + params.help = true; + break; + case 'v': + params.version = true; + break; + case 'c': + params.ca = optarg; + break; + case 'i': + params.id = optarg; + break; + case 'p': + params.privatekey = optarg; + break; + case 'g': + params.pkid = true; + break; + case 'n': + params.name = optarg; + break; + case 's': + params.setup = true; + break; + default: + std::cerr << "Invalid option" << std::endl; + exit(EXIT_FAILURE); + } + } + + if (params.id.empty() && !params.pkid) { + std::cerr << "Error: The path to save the generated identity is not provided.\n Please specify the path for saving the generated identity using the -i option.\n"; exit(EXIT_FAILURE); + } + return params; +} + + +int +main(int argc, char** argv) +{ + auto params = parse_args(argc, argv); + + if (params.help) { + fmt::print("Usage: dhtnet-crtmgr [options]\n" + "\nOptions:\n" + " -h, --help Display this help message and then exit.\n" + " -v, --version Show the version of the program.\n" + " -p, --privatekey Provide the path to the private key as an argument.\n" + " -c, --CA Provide the path to the Certificate Authority as an argument.\n" + " -i, --id Provide the path where the generated identity should be saved as an argument.\n" + " -g, --pkid Display the publickey id used by the server dnc.\n" + " -n, --name Provide the name of the identity to be generated.\n" + " -s, --setup Create an CA and an id.\n"); + return EXIT_SUCCESS; + } + + if (params.version) { + fmt::print("dhtnet-crtmgr v1.0\n"); + return EXIT_SUCCESS; + } + // check if the public key id is requested + if (params.pkid) { + if (params.ca.empty() || params.privatekey.empty()) { + fmt::print(stderr, "Error: The path to the private key and the Certificate Authority is not provided.\n Please specify the path for the private key and the Certificate Authority using the -p and -c options.\n"); + exit(EXIT_FAILURE); + } + auto identity = dhtnet::loadIdentity(params.privatekey, params.ca); + fmt::print("Public key id: {}\n", identity.second->getId()); + return EXIT_SUCCESS; + } + + // check if the setup is requested + if (params.setup) { + // create CA with name ca-server + std::filesystem::path path_ca = params.id / "CA"; + auto ca = dhtnet::generateIdentity(path_ca, "ca-server"); + fmt::print("Generated CA in {}: {} {}\n", path_ca, "ca-server", ca.second->getId()); + // create identity with name id-server + std::filesystem::path path_id = params.id / "id"; + auto identity = dhtnet::generateIdentity(path_id, "id-server", ca); + fmt::print("Generated identity in {}: {} {}\n", path_id,"id-server", identity.second->getId()); + return EXIT_SUCCESS; + } + + if (params.ca.empty() || params.privatekey.empty()) { + if (params.name.empty()) { + auto ca = dhtnet::generateIdentity(params.id, "ca"); + fmt::print("Generated CA in {}: {} {}\n", params.id, "ca", ca.second->getId()); + }else{ + auto ca = dhtnet::generateIdentity(params.id, params.name); + fmt::print("Generated CA in {}: {} {}\n", params.id, params.name, ca.second->getId()); + } + }else{ + auto ca = dhtnet::loadIdentity(params.privatekey, params.ca); + if (params.name.empty()) { + auto id = dhtnet::generateIdentity(params.id, "id", ca); + fmt::print("Generated identity in {}: {} {}\n", params.id, "id", id.second->getId()); + }else{ + auto id = dhtnet::generateIdentity(params.id, params.name, ca); + fmt::print("Generated identity in {}: {} {}\n", params.id, params.name, id.second->getId()); + } + } + return EXIT_SUCCESS; +} diff --git a/tools/dnc/main.cpp b/tools/dnc/main.cpp index 363e05e6d30f4459356b32c67d4e3affe085760b..02debd54e6c12f01faaacb858bc8667e83b114dd 100644 --- a/tools/dnc/main.cpp +++ b/tools/dnc/main.cpp @@ -16,6 +16,7 @@ */ #include "dnc.h" #include "common.h" +#include "dhtnet_crtmgr/dhtnet_crtmgr.h" #include <string> #include <vector> diff --git a/tools/dsh/main.cpp b/tools/dsh/main.cpp index 19ff4e5950e20ef59cb8cddbd69e29b7a863a898..0e91e91f72c2de14343d17308c61449ee55764f7 100644 --- a/tools/dsh/main.cpp +++ b/tools/dsh/main.cpp @@ -16,6 +16,8 @@ */ #include "dsh.h" #include "../common.h" +#include "dhtnet_crtmgr/dhtnet_crtmgr.h" + #include <string> #include <vector> #include <iostream> diff --git a/tools/dvpn/main.cpp b/tools/dvpn/main.cpp index 5b1945900da02e2d833854663ac3b9e77ce313f2..8cbeebc208b74d1e7cae2c4ec3e24375a7a1e970 100644 --- a/tools/dvpn/main.cpp +++ b/tools/dvpn/main.cpp @@ -16,6 +16,7 @@ */ #include "dvpn.h" #include "common.h" +#include "dhtnet_crtmgr/dhtnet_crtmgr.h" #include <string> #include <vector>