From ef7553e46073f831a29ff179d32e5d49fff71a25 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Tue, 16 Nov 2021 07:56:02 +0100 Subject: [PATCH] Refs #12943: backport PKCS#11 support to Galactic Signed-off-by: JLBuenoLopez-eProsima --- rmw_fastrtps_shared_cpp/src/participant.cpp | 164 +++++++++++++++----- 1 file changed, 125 insertions(+), 39 deletions(-) diff --git a/rmw_fastrtps_shared_cpp/src/participant.cpp b/rmw_fastrtps_shared_cpp/src/participant.cpp index 90ebed03df..c7a92c095d 100644 --- a/rmw_fastrtps_shared_cpp/src/participant.cpp +++ b/rmw_fastrtps_shared_cpp/src/participant.cpp @@ -16,6 +16,9 @@ #include #include #include +#include +#include +#include #include "fastdds/dds/core/status/StatusMask.hpp" #include "fastdds/dds/domain/DomainParticipantFactory.hpp" @@ -32,6 +35,7 @@ #include "fastdds/rtps/transport/shared_mem/SharedMemTransportDescriptor.h" #include "rcpputils/scope_exit.hpp" +#include "rcpputils/filesystem_helper.hpp" #include "rcutils/filesystem.h" #include "rcutils/get_env.h" @@ -44,36 +48,117 @@ #include "rmw_fastrtps_shared_cpp/utils.hpp" #if HAVE_SECURITY +// Processor for security attributes with FILE URI +bool +process_file_uri_security_file( + const std::string & prefix, const rcpputils::fs::path & full_path, + std::string & result) +{ + if (!full_path.is_regular_file()) { + return false; + } + result = prefix + full_path.string(); + return true; +} + +// Processor for security attributes with PKCS#11 URI +bool +process_pkcs_uri_security_file( + const std::string & /*prefix*/, const rcpputils::fs::path & full_path, + std::string & result) +{ + const std::string p11_prefix("pkcs11:"); + + std::ifstream ifs(full_path.string()); + if (!ifs.is_open()) { + return false; + } + if (!(ifs >> result)) { + return false; + } + if (result.find(p11_prefix) != 0) { + return false; + } + + return true; +} + static bool -get_security_file_paths( - std::array & security_files_paths, const char * secure_root) +get_security_files( + const std::string & prefix, const std::string & secure_root, + std::unordered_map & result) { - // here assume only 6 files for security - const char * file_names[6] = { - "identity_ca.cert.pem", "cert.pem", "key.pem", - "permissions_ca.cert.pem", "governance.p7s", "permissions.p7s" + using std::placeholders::_1; + using std::placeholders::_2; + using std::placeholders::_3; + using security_file_processor = + std::function; + using processor_vector = + std::vector>; + + // Key: the security attribute + // Value: ordered sequence of pairs. Each pair contains one possible file name + // for the attribute and the corresponding processor method + // Pairs are ordered by priority: the first one matching is used. + const std::unordered_map required_files{ + {"IDENTITY_CA", { + {"identity_ca.cert.pem", std::bind(process_file_uri_security_file, _1, _2, _3)}, + {"identity_ca.cert.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3)}}}, + {"CERTIFICATE", { + {"cert.pem", std::bind(process_file_uri_security_file, _1, _2, _3)}, + {"cert.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3)}}}, + {"PRIVATE_KEY", { + {"key.pem", std::bind(process_file_uri_security_file, _1, _2, _3)}, + {"key.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3)}}}, + {"PERMISSIONS_CA", { + {"permissions_ca.cert.pem", std::bind(process_file_uri_security_file, _1, _2, _3)}, + {"permissions_ca.cert.p11", std::bind(process_pkcs_uri_security_file, _1, _2, _3)}}}, + {"GOVERNANCE", { + {"governance.p7s", std::bind(process_file_uri_security_file, _1, _2, _3)}}}, + {"PERMISSIONS", { + {"permissions.p7s", std::bind(process_file_uri_security_file, _1, _2, _3)}}}, }; - size_t num_files = sizeof(file_names) / sizeof(char *); - std::string file_prefix("file://"); - - for (size_t i = 0; i < num_files; i++) { - rcutils_allocator_t allocator = rcutils_get_default_allocator(); - char * file_path = rcutils_join_path(secure_root, file_names[i], allocator); + const std::unordered_map optional_files{ + {"CRL", { + {"crl.pem", std::bind(process_file_uri_security_file, _1, _2, _3)}}} + }; - if (!file_path) { - return false; + for (const std::pair>> & el : required_files) + { + std::string attribute_value; + bool processed = false; + for (auto & proc : el.second) { + rcpputils::fs::path full_path(secure_root); + full_path /= proc.first; + if (proc.second(prefix, full_path, attribute_value)) { + processed = true; + break; + } } - - if (rcutils_is_readable(file_path)) { - security_files_paths[i] = file_prefix + std::string(file_path); - } else { - allocator.deallocate(file_path, allocator.state); + if (!processed) { + result.clear(); return false; } + result[el.first] = attribute_value; + } - allocator.deallocate(file_path, allocator.state); + for (const std::pair & el : optional_files) { + std::string attribute_value; + bool processed = false; + for (auto & proc : el.second) { + rcpputils::fs::path full_path(secure_root); + full_path /= proc.first; + if (proc.second(prefix, full_path, attribute_value)) { + processed = true; + break; + } + } + if (processed) { + result[el.first] = attribute_value; + } } return true; @@ -264,36 +349,37 @@ rmw_fastrtps_shared_cpp::create_participant( if (security_options->security_root_path) { // if security_root_path provided, try to find the key and certificate files #if HAVE_SECURITY - std::array security_files_paths; - if (get_security_file_paths(security_files_paths, security_options->security_root_path)) { + std::unordered_map security_files_paths; + if (get_security_files( + "file://", security_options->security_root_path, security_files_paths)) { eprosima::fastrtps::rtps::PropertyPolicy property_policy; - using Property = eprosima::fastrtps::rtps::Property; property_policy.properties().emplace_back( - Property("dds.sec.auth.plugin", "builtin.PKI-DH")); + "dds.sec.auth.plugin", "builtin.PKI-DH"); property_policy.properties().emplace_back( - Property( - "dds.sec.auth.builtin.PKI-DH.identity_ca", security_files_paths[0])); + "dds.sec.auth.builtin.PKI-DH.identity_ca", security_files_paths["IDENTITY_CA"]); property_policy.properties().emplace_back( - Property( - "dds.sec.auth.builtin.PKI-DH.identity_certificate", security_files_paths[1])); + "dds.sec.auth.builtin.PKI-DH.identity_certificate", security_files_paths["CERTIFICATE"]); property_policy.properties().emplace_back( - Property( - "dds.sec.auth.builtin.PKI-DH.private_key", security_files_paths[2])); + "dds.sec.auth.builtin.PKI-DH.private_key", security_files_paths["PRIVATE_KEY"]); property_policy.properties().emplace_back( - Property("dds.sec.crypto.plugin", "builtin.AES-GCM-GMAC")); + "dds.sec.crypto.plugin", "builtin.AES-GCM-GMAC"); property_policy.properties().emplace_back( - Property( - "dds.sec.access.plugin", "builtin.Access-Permissions")); + "dds.sec.access.plugin", "builtin.Access-Permissions"); property_policy.properties().emplace_back( - Property( - "dds.sec.access.builtin.Access-Permissions.permissions_ca", security_files_paths[3])); + "dds.sec.access.builtin.Access-Permissions.permissions_ca", + security_files_paths["PERMISSIONS_CA"]); property_policy.properties().emplace_back( - Property( - "dds.sec.access.builtin.Access-Permissions.governance", security_files_paths[4])); + "dds.sec.access.builtin.Access-Permissions.governance", + security_files_paths["GOVERNANCE"]); property_policy.properties().emplace_back( - Property( - "dds.sec.access.builtin.Access-Permissions.permissions", security_files_paths[5])); + "dds.sec.access.builtin.Access-Permissions.permissions", + security_files_paths["PERMISSIONS"]); + + if (security_files_paths.count("CRL") > 0) { + property_policy.properties().emplace_back( + "dds.sec.auth.builtin.PKI-DH.identity_crl", security_files_paths["CRL"]); + } // Configure security logging if (!apply_security_logging_configuration(property_policy)) {