diff --git a/rcl/include/rcl/security_directory.h b/rcl/include/rcl/security_directory.h index 09d9f78e9..8e9985a81 100644 --- a/rcl/include/rcl/security_directory.h +++ b/rcl/include/rcl/security_directory.h @@ -15,7 +15,13 @@ #ifndef RCL__SECURITY_DIRECTORY_H_ #define RCL__SECURITY_DIRECTORY_H_ +#ifdef __cplusplus +extern "C" +{ +#endif + #include "rcl/allocator.h" +#include "rcl/visibility_control.h" #ifndef ROS_SECURITY_NODE_DIRECTORY_VAR_NAME #define ROS_SECURITY_NODE_DIRECTORY_VAR_NAME "ROS_SECURITY_NODE_DIRECTORY" @@ -29,11 +35,6 @@ #define ROS_SECURITY_LOOKUP_TYPE_VAR_NAME "ROS_SECURITY_LOOKUP_TYPE" #endif -#ifdef __cplusplus -extern "C" -{ -#endif - /// Return the secure root directory associated with a node given its validated name and namespace. /** * E.g. for a node named "c" in namespace "/a/b", the secure root path will be @@ -50,10 +51,11 @@ extern "C" * \param[in] allocator the allocator to use for allocation * \returns machine specific (absolute) node secure root path or NULL on failure */ +RCL_PUBLIC const char * rcl_get_secure_root( - const char * node_name, - const char * node_namespace, - const rcl_allocator_t * allocator + const char * node_name, + const char * node_namespace, + const rcl_allocator_t * allocator ); #ifdef __cplusplus diff --git a/rcl/src/rcl/security_directory.c b/rcl/src/rcl/security_directory.c index 65f7f809f..2b2d55fda 100644 --- a/rcl/src/rcl/security_directory.c +++ b/rcl/src/rcl/security_directory.c @@ -24,143 +24,151 @@ * It returns the relevant information required to load the security credentials, * which is currently a path to a directory on the filesystem containing DDS Security permission files. */ -typedef char * (*security_lookup_fn_t) ( - const char * node_name, - const char * node_namespace, - const char * ros_secure_root_env, - const rcl_allocator_t * allocator +typedef char * (* security_lookup_fn_t) ( + const char * node_name, + const char * node_namespace, + const char * ros_secure_root_env, + const rcl_allocator_t * allocator ); -char * exact_match_lookup ( - const char * node_name, - const char * node_namespace, - const char * ros_secure_root_env, - const rcl_allocator_t * allocator +char * exact_match_lookup( + const char * node_name, + const char * node_namespace, + const char * ros_secure_root_env, + const rcl_allocator_t * allocator ); -char * prefix_match_lookup ( - const char * node_name, - const char * node_namespace, - const char * ros_secure_root_env, - const rcl_allocator_t * allocator +char * prefix_match_lookup( + const char * node_name, + const char * node_namespace, + const char * ros_secure_root_env, + const rcl_allocator_t * allocator ); security_lookup_fn_t g_security_lookup_fns[] = { - NULL, - exact_match_lookup, - prefix_match_lookup, + NULL, + exact_match_lookup, + prefix_match_lookup, }; -typedef enum ros_security_lookup_type_e { - ROS_SECURITY_LOOKUP_NODE_OVERRIDE = 0, - ROS_SECURITY_LOOKUP_MATCH_EXACT = 1, - ROS_SECURITY_LOOKUP_MATCH_PREFIX = 2, +typedef enum ros_security_lookup_type_e +{ + ROS_SECURITY_LOOKUP_NODE_OVERRIDE = 0, + ROS_SECURITY_LOOKUP_MATCH_EXACT = 1, + ROS_SECURITY_LOOKUP_MATCH_PREFIX = 2, } ros_security_lookup_type_t; char * g_security_lookup_type_strings[] = { - "NODE_OVERRIDE", - "MATCH_EXACT", - "MATCH_PREFIX" + "NODE_OVERRIDE", + "MATCH_EXACT", + "MATCH_PREFIX" }; -/// Return the directory whose name most closely matches node_name (longest-prefix match), scanning under base_dir. +/// Return the directory whose name most closely matches node_name (longest-prefix match), +/// scanning under base_dir. /** - * By using a prefix match, a node named e.g. "my_node_123" will be able to load and use the directory "my_node" if no better match exists. + * By using a prefix match, a node named e.g. "my_node_123" will be able to load and use the + * directory "my_node" if no better match exists. * \param[in] base_dir * \param[in] node_name - * \param[out] matched_name must be a valid memory address allocated with at least _TINYDIR_FILENAME_MAX characters. + * \param[out] matched_name must be a valid memory address allocated with at least + * _TINYDIR_FILENAME_MAX characters. * \return true if a match was found */ static bool get_best_matching_directory( - const char * base_dir, - const char * node_name, - char * matched_name) + const char * base_dir, + const char * node_name, + char * matched_name) { - size_t max_match_length = 0; - tinydir_dir dir; - if (NULL == base_dir || NULL == node_name || NULL == matched_name) { - return false; + size_t max_match_length = 0; + tinydir_dir dir; + if (NULL == base_dir || NULL == node_name || NULL == matched_name) { + return false; + } + if (-1 == tinydir_open(&dir, base_dir)) { + return false; + } + while (dir.has_next) { + tinydir_file file; + if (-1 == tinydir_readfile(&dir, &file)) { + goto cleanup; } - if (-1 == tinydir_open(&dir, base_dir)) { - return false; + if (file.is_dir) { + size_t matched_name_length = strnlen(file.name, sizeof(file.name) - 1); + if (0 == + strncmp(file.name, node_name, + matched_name_length) && matched_name_length > max_match_length) + { + max_match_length = matched_name_length; + strncpy(matched_name, file.name, max_match_length); + } } - while (dir.has_next) { - tinydir_file file; - if (-1 == tinydir_readfile(&dir, &file)) { - goto cleanup; - } - if (file.is_dir) { - size_t matched_name_length = strnlen(file.name, sizeof(file.name) - 1); - if (0 == strncmp(file.name, node_name, matched_name_length) && matched_name_length > max_match_length) { - max_match_length = matched_name_length; - strncpy(matched_name, file.name, max_match_length); - } - } - if (-1 == tinydir_next(&dir)) { - goto cleanup; - } + if (-1 == tinydir_next(&dir)) { + goto cleanup; } - cleanup: - tinydir_close(&dir); - return max_match_length > 0; + } +cleanup: + tinydir_close(&dir); + return max_match_length > 0; } -char * exact_match_lookup ( - const char * node_name, - const char * node_namespace, - const char * ros_secure_root_env, - const rcl_allocator_t * allocator -) { - // Perform longest prefix match for the node's name in directory /. - char * node_secure_root = NULL; - if (1 == strlen(node_namespace)) { - node_secure_root = rcutils_join_path(ros_secure_root_env, node_name, *allocator); - } else { - char * node_fqn = NULL; - char * node_root_path = NULL; - // Combine node namespace with node name - // TODO(ros2team): remove the hard-coded value of the root namespace - node_fqn = rcutils_format_string(*allocator, "%s%s%s", node_namespace, "/", node_name); - // Get native path, ignore the leading forward slash - // TODO(ros2team): remove the hard-coded length, use the length of the root namespace instead - node_root_path = rcutils_to_native_path(node_fqn + 1, *allocator); - node_secure_root = rcutils_join_path(ros_secure_root_env, node_root_path, *allocator); - allocator->deallocate(node_fqn, allocator->state); - allocator->deallocate(node_root_path, allocator->state); - } - return node_secure_root; +char * exact_match_lookup( + const char * node_name, + const char * node_namespace, + const char * ros_secure_root_env, + const rcl_allocator_t * allocator) +{ + // Perform longest prefix match for the node's name in directory /. + char * node_secure_root = NULL; + if (1 == strlen(node_namespace)) { + node_secure_root = rcutils_join_path(ros_secure_root_env, node_name, *allocator); + } else { + char * node_fqn = NULL; + char * node_root_path = NULL; + // Combine node namespace with node name + // TODO(ros2team): remove the hard-coded value of the root namespace + node_fqn = rcutils_format_string(*allocator, "%s%s%s", node_namespace, "/", node_name); + // Get native path, ignore the leading forward slash + // TODO(ros2team): remove the hard-coded length, use the length of the root namespace instead + node_root_path = rcutils_to_native_path(node_fqn + 1, *allocator); + node_secure_root = rcutils_join_path(ros_secure_root_env, node_root_path, *allocator); + allocator->deallocate(node_fqn, allocator->state); + allocator->deallocate(node_root_path, allocator->state); + } + return node_secure_root; } -char * prefix_match_lookup ( - const char * node_name, - const char * node_namespace, - const char * ros_secure_root_env, - const rcl_allocator_t * allocator -) { - // Perform longest prefix match for the node's name in directory /. - char * node_secure_root = NULL; - char matched_dir[_TINYDIR_FILENAME_MAX] = {0}; - char * base_lookup_dir = NULL; - if (strlen(node_namespace) == 1) { - base_lookup_dir = (char *) ros_secure_root_env; - } else { - // TODO(ros2team): remove the hard-coded length, use the length of the root namespace instead. - base_lookup_dir = rcutils_join_path(ros_secure_root_env, node_namespace + 1, *allocator); - } - if (get_best_matching_directory(base_lookup_dir, node_name, matched_dir)) { - node_secure_root = rcutils_join_path(base_lookup_dir, matched_dir, *allocator); - } - if (base_lookup_dir != ros_secure_root_env && NULL != base_lookup_dir) { - allocator->deallocate(base_lookup_dir, allocator->state); - } - return node_secure_root; +char * prefix_match_lookup( + const char * node_name, + const char * node_namespace, + const char * ros_secure_root_env, + const rcl_allocator_t * allocator) +{ + // Perform longest prefix match for the node's name in directory /. + char * node_secure_root = NULL; + char matched_dir[_TINYDIR_FILENAME_MAX] = {0}; + char * base_lookup_dir = NULL; + if (strlen(node_namespace) == 1) { + base_lookup_dir = (char *) ros_secure_root_env; + } else { + // TODO(ros2team): remove the hard-coded length, use the length of the root namespace instead. + base_lookup_dir = rcutils_join_path(ros_secure_root_env, node_namespace + 1, *allocator); + } + if (get_best_matching_directory(base_lookup_dir, node_name, matched_dir)) { + node_secure_root = rcutils_join_path(base_lookup_dir, matched_dir, *allocator); + } + if (base_lookup_dir != ros_secure_root_env && NULL != base_lookup_dir) { + allocator->deallocate(base_lookup_dir, allocator->state); + } + return node_secure_root; } /// Return the secure root directory associated with a node given its validated name and namespace. /** * E.g. for a node named "c" in namespace "/a/b", the secure root path will be * "a/b/c", where the delimiter "/" is native for target file system (e.g. "\\" for _WIN32). - * If no exact match is found for the node name, a best match would be used instead (by performing longest-prefix matching). + * If no exact match is found for the node name, a best match would be used instead + * (by performing longest-prefix matching). * * However, this expansion can be overridden by setting the secure node directory environment * variable, allowing users to explicitly specify the exact secure root directory to be utilized. @@ -173,77 +181,79 @@ char * prefix_match_lookup ( * \returns machine specific (absolute) node secure root path or NULL on failure */ const char * rcl_get_secure_root( - const char * node_name, - const char * node_namespace, - const rcl_allocator_t * allocator) + const char * node_name, + const char * node_namespace, + const rcl_allocator_t * allocator) { - bool ros_secure_node_override = true; - const char * ros_secure_root_env = NULL; - if (NULL == node_name) { - return NULL; - } - if (rcutils_get_env(ROS_SECURITY_NODE_DIRECTORY_VAR_NAME, &ros_secure_root_env)) { - return NULL; + bool ros_secure_node_override = true; + const char * ros_secure_root_env = NULL; + if (NULL == node_name) { + return NULL; + } + if (rcutils_get_env(ROS_SECURITY_NODE_DIRECTORY_VAR_NAME, &ros_secure_root_env)) { + return NULL; + } + if (!ros_secure_root_env) { + return NULL; + } + size_t ros_secure_root_size = strlen(ros_secure_root_env); + if (!ros_secure_root_size) { + // check root directory if node directory environment variable is empty + if (rcutils_get_env(ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME, &ros_secure_root_env)) { + return NULL; } if (!ros_secure_root_env) { - return NULL; + return NULL; } - size_t ros_secure_root_size = strlen(ros_secure_root_env); + ros_secure_root_size = strlen(ros_secure_root_env); if (!ros_secure_root_size) { - // check root directory if node directory environment variable is empty - if (rcutils_get_env(ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME, &ros_secure_root_env)) { - return NULL; - } - if (!ros_secure_root_env) { - return NULL; - } - ros_secure_root_size = strlen(ros_secure_root_env); - if (!ros_secure_root_size) { - return NULL; // environment variable was empty - } else { - ros_secure_node_override = false; - } + return NULL; // environment variable was empty + } else { + ros_secure_node_override = false; } + } - char * node_secure_root = NULL; - char * lookup_strategy = NULL; - if (ros_secure_node_override) { - node_secure_root = - (char *)allocator->allocate(ros_secure_root_size + 1, allocator->state); - memcpy(node_secure_root, ros_secure_root_env, ros_secure_root_size + 1); - lookup_strategy = g_security_lookup_type_strings[ROS_SECURITY_LOOKUP_NODE_OVERRIDE]; - // TODO(ros2team): This make an assumption on the value and length of the root namespace. - // This should likely come from another (rcl/rmw?) function for reuse. - // If the namespace is the root namespace ("/"), the secure root is just the node name. - } else { - // Check which lookup method to use and invoke the relevant function. - const char * ros_security_lookup_type = NULL; - if (rcutils_get_env(ROS_SECURITY_LOOKUP_TYPE_VAR_NAME, &ros_security_lookup_type)) { - return NULL; - } - if (0 == strcmp(ros_security_lookup_type, - g_security_lookup_type_strings[ROS_SECURITY_LOOKUP_MATCH_PREFIX])) { - node_secure_root = g_security_lookup_fns[ROS_SECURITY_LOOKUP_MATCH_PREFIX] - (node_name, node_namespace, ros_secure_root_env, allocator); - lookup_strategy = g_security_lookup_type_strings[ROS_SECURITY_LOOKUP_MATCH_PREFIX]; - } else { /* Default is MATCH_EXACT */ - node_secure_root = g_security_lookup_fns[ROS_SECURITY_LOOKUP_MATCH_EXACT] - (node_name, node_namespace, ros_secure_root_env, allocator); - lookup_strategy = g_security_lookup_type_strings[ROS_SECURITY_LOOKUP_MATCH_EXACT]; - } + char * node_secure_root = NULL; + char * lookup_strategy = NULL; + if (ros_secure_node_override) { + node_secure_root = + (char *)allocator->allocate(ros_secure_root_size + 1, allocator->state); + memcpy(node_secure_root, ros_secure_root_env, ros_secure_root_size + 1); + lookup_strategy = g_security_lookup_type_strings[ROS_SECURITY_LOOKUP_NODE_OVERRIDE]; + // TODO(ros2team): This make an assumption on the value and length of the root namespace. + // This should likely come from another (rcl/rmw?) function for reuse. + // If the namespace is the root namespace ("/"), the secure root is just the node name. + } else { + // Check which lookup method to use and invoke the relevant function. + const char * ros_security_lookup_type = NULL; + if (rcutils_get_env(ROS_SECURITY_LOOKUP_TYPE_VAR_NAME, &ros_security_lookup_type)) { + return NULL; } - // Check node_secure_root is not NULL before checking directory - if (NULL == node_secure_root) { - RCL_SET_ERROR_MSG_WITH_FORMAT_STRING( - "SECURITY ERROR: unable to find a folder matching the node name in %s%s. Lookup strategy: %s", - ros_secure_root_env, node_namespace, lookup_strategy); - } else if (!rcutils_is_directory(node_secure_root)) { - RCL_SET_ERROR_MSG_WITH_FORMAT_STRING( - "SECURITY ERROR: directory %s does not exist. Lookup strategy: %s", - node_secure_root, lookup_strategy); - allocator->deallocate(node_secure_root, allocator->state); - } else { - return node_secure_root; + if (0 == strcmp(ros_security_lookup_type, + g_security_lookup_type_strings[ROS_SECURITY_LOOKUP_MATCH_PREFIX])) + { + node_secure_root = g_security_lookup_fns[ROS_SECURITY_LOOKUP_MATCH_PREFIX] + (node_name, node_namespace, ros_secure_root_env, allocator); + lookup_strategy = g_security_lookup_type_strings[ROS_SECURITY_LOOKUP_MATCH_PREFIX]; + } else { /* Default is MATCH_EXACT */ + node_secure_root = g_security_lookup_fns[ROS_SECURITY_LOOKUP_MATCH_EXACT] + (node_name, node_namespace, ros_secure_root_env, allocator); + lookup_strategy = g_security_lookup_type_strings[ROS_SECURITY_LOOKUP_MATCH_EXACT]; } - return NULL; + } + // Check node_secure_root is not NULL before checking directory + if (NULL == node_secure_root) { + RCL_SET_ERROR_MSG_WITH_FORMAT_STRING( + "SECURITY ERROR: unable to find a folder matching the node name in %s%s." + "Lookup strategy: %s", + ros_secure_root_env, node_namespace, lookup_strategy); + } else if (!rcutils_is_directory(node_secure_root)) { + RCL_SET_ERROR_MSG_WITH_FORMAT_STRING( + "SECURITY ERROR: directory %s does not exist. Lookup strategy: %s", + node_secure_root, lookup_strategy); + allocator->deallocate(node_secure_root, allocator->state); + } else { + return node_secure_root; + } + return NULL; } diff --git a/rcl/test/CMakeLists.txt b/rcl/test/CMakeLists.txt index c59fa19c7..6e17bd7ce 100644 --- a/rcl/test/CMakeLists.txt +++ b/rcl/test/CMakeLists.txt @@ -308,5 +308,5 @@ rcl_add_custom_gtest(test_security_directory ) # Install test resources -INSTALL(DIRECTORY ${test_resources_dir_name} +install(DIRECTORY ${test_resources_dir_name} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/rcl/test/rcl/test_security_directory.cpp b/rcl/test/rcl/test_security_directory.cpp index 31d94aa9e..6f43ab4cd 100644 --- a/rcl/test/rcl/test_security_directory.cpp +++ b/rcl/test/rcl/test_security_directory.cpp @@ -15,107 +15,125 @@ #include +#include #include "rcl/security_directory.h" #include "rcutils/filesystem.h" -#include #define ROOT_NAMESPACE "/" #define TEST_SECURITY_DIRECTORY_RESOURCES_DIR_NAME "test_security_directory" #define TEST_NODE_NAME "dummy_node" #define TEST_NODE_NAMESPACE ROOT_NAMESPACE TEST_SECURITY_DIRECTORY_RESOURCES_DIR_NAME -static int putenv_wrapper(const char * env_var) { +static int putenv_wrapper(const char * env_var) +{ #ifdef _WIN32 - return _putenv(env_var); + return _putenv(env_var); #else - return putenv((char *) env_var); + return putenv(reinterpret_cast(const_cast(env_var))); #endif } TEST(test_rcl_get_secure_root, failureScenarios) { - rcl_allocator_t allocator = rcl_get_default_allocator(); - /* Before setting the environment variable */ - ASSERT_EQ(rcl_get_secure_root(TEST_NODE_NAME, TEST_NODE_NAMESPACE, &allocator), - (char *) NULL); + rcl_allocator_t allocator = rcl_get_default_allocator(); + /* Before setting the environment variable */ + ASSERT_EQ(rcl_get_secure_root(TEST_NODE_NAME, TEST_NODE_NAMESPACE, &allocator), + (char *) NULL); - putenv_wrapper(ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME "=" TEST_RESOURCES_DIRECTORY); + putenv_wrapper(ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME "=" TEST_RESOURCES_DIRECTORY); - /* Security directory is set, but there's no matching directory */ - /// Wrong namespace - ASSERT_EQ(rcl_get_secure_root(TEST_NODE_NAME, "/some_other_namespace", &allocator), - (char *) NULL); - /// Wrong node name - ASSERT_EQ(rcl_get_secure_root("not_" TEST_NODE_NAME, TEST_NODE_NAMESPACE, &allocator), - (char *) NULL); + /* Security directory is set, but there's no matching directory */ + /// Wrong namespace + ASSERT_EQ(rcl_get_secure_root(TEST_NODE_NAME, "/some_other_namespace", &allocator), + (char *) NULL); + /// Wrong node name + ASSERT_EQ(rcl_get_secure_root("not_" TEST_NODE_NAME, TEST_NODE_NAMESPACE, &allocator), + (char *) NULL); } TEST(test_rcl_get_secure_root, successScenarios) { - rcl_allocator_t allocator = rcl_get_default_allocator(); - putenv_wrapper(ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME "=" TEST_RESOURCES_DIRECTORY); - /* -------------------------- - * Namespace : Custom (local) - * Match type : Exact - * -------------------------- - * Root: ${CMAKE_BINARY_DIR}/tests/resources - * Namespace: /test_security_directory - * Node: dummy_node - */ - std::string secure_root = rcl_get_secure_root(TEST_NODE_NAME, TEST_NODE_NAMESPACE, &allocator); - ASSERT_STREQ(TEST_NODE_NAME, secure_root.substr(secure_root.size() - (sizeof(TEST_NODE_NAME) - 1)).c_str()); + rcl_allocator_t allocator = rcl_get_default_allocator(); + putenv_wrapper(ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME "=" TEST_RESOURCES_DIRECTORY); + /* -------------------------- + * Namespace : Custom (local) + * Match type : Exact + * -------------------------- + * Root: ${CMAKE_BINARY_DIR}/tests/resources + * Namespace: /test_security_directory + * Node: dummy_node + */ + std::string secure_root = rcl_get_secure_root(TEST_NODE_NAME, TEST_NODE_NAMESPACE, &allocator); + ASSERT_STREQ(TEST_NODE_NAME, + secure_root.substr(secure_root.size() - (sizeof(TEST_NODE_NAME) - 1)).c_str()); - /* -------------------------- - * Namespace : Custom (local) - * Match type : Prefix - * -------------------------- - * Root: ${CMAKE_BINARY_DIR}/tests/resources - * Namespace: /test_security_directory - * Node: dummy_node_and_some_suffix_added */ - ASSERT_STRNE(rcl_get_secure_root(TEST_NODE_NAME "_and_some_suffix_added", TEST_NODE_NAMESPACE, &allocator), - secure_root.c_str()); - putenv_wrapper(ROS_SECURITY_LOOKUP_TYPE_VAR_NAME "=MATCH_PREFIX"); - ASSERT_STREQ(rcl_get_secure_root(TEST_NODE_NAME "_and_some_suffix_added", TEST_NODE_NAMESPACE, &allocator), - secure_root.c_str()); + /* -------------------------- + * Namespace : Custom (local) + * Match type : Prefix + * -------------------------- + * Root: ${CMAKE_BINARY_DIR}/tests/resources + * Namespace: /test_security_directory + * Node: dummy_node_and_some_suffix_added */ + ASSERT_STRNE(rcl_get_secure_root(TEST_NODE_NAME "_and_some_suffix_added", TEST_NODE_NAMESPACE, + &allocator), + secure_root.c_str()); + putenv_wrapper(ROS_SECURITY_LOOKUP_TYPE_VAR_NAME "=MATCH_PREFIX"); + ASSERT_STREQ(rcl_get_secure_root(TEST_NODE_NAME "_and_some_suffix_added", TEST_NODE_NAMESPACE, + &allocator), + secure_root.c_str()); - /* Include the namespace as part of the root security directory and test root namespace */ - char * base_lookup_dir_fqn = rcutils_join_path(TEST_RESOURCES_DIRECTORY, TEST_SECURITY_DIRECTORY_RESOURCES_DIR_NAME, allocator); - std::string putenv_input = ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME "="; - putenv_input += base_lookup_dir_fqn; - putenv_wrapper(putenv_input.c_str()); - /* -------------------------- - * Namespace : Root - * Match type : Exact - * -------------------------- - * Root: ${CMAKE_BINARY_DIR}/tests/resources/test_security_directory - * Namespace: / - * Node: dummy_node */ - ASSERT_STREQ(rcl_get_secure_root(TEST_NODE_NAME, ROOT_NAMESPACE, &allocator), secure_root.c_str()); - putenv_wrapper(ROS_SECURITY_LOOKUP_TYPE_VAR_NAME "=MATCH_EXACT"); - ASSERT_STREQ(rcl_get_secure_root(TEST_NODE_NAME, ROOT_NAMESPACE, &allocator), secure_root.c_str()); + /* Include the namespace as part of the root security directory and test root namespace */ + char * base_lookup_dir_fqn = rcutils_join_path(TEST_RESOURCES_DIRECTORY, + TEST_SECURITY_DIRECTORY_RESOURCES_DIR_NAME, allocator); + std::string putenv_input = ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME "="; + putenv_input += base_lookup_dir_fqn; + putenv_wrapper(putenv_input.c_str()); + /* -------------------------- + * Namespace : Root + * Match type : Exact + * -------------------------- + * Root: ${CMAKE_BINARY_DIR}/tests/resources/test_security_directory + * Namespace: / + * Node: dummy_node */ + ASSERT_STREQ(rcl_get_secure_root(TEST_NODE_NAME, ROOT_NAMESPACE, + &allocator), + secure_root.c_str()); + putenv_wrapper(ROS_SECURITY_LOOKUP_TYPE_VAR_NAME "=MATCH_EXACT"); + ASSERT_STREQ(rcl_get_secure_root(TEST_NODE_NAME, ROOT_NAMESPACE, + &allocator), + secure_root.c_str()); - /* -------------------------- - * Namespace : Root - * Match type : Prefix - * -------------------------- - * Root dir: ${CMAKE_BINARY_DIR}/tests/resources/test_security_directory - * Namespace: / - * Node: dummy_node_and_some_suffix_added */ - ASSERT_STRNE(rcl_get_secure_root(TEST_NODE_NAME "_and_some_suffix_added", ROOT_NAMESPACE, &allocator), secure_root.c_str()); - putenv_wrapper(ROS_SECURITY_LOOKUP_TYPE_VAR_NAME "=MATCH_PREFIX"); - ASSERT_STREQ(rcl_get_secure_root(TEST_NODE_NAME "_and_some_suffix_added", ROOT_NAMESPACE, &allocator), secure_root.c_str()); + /* -------------------------- + * Namespace : Root + * Match type : Prefix + * -------------------------- + * Root dir: ${CMAKE_BINARY_DIR}/tests/resources/test_security_directory + * Namespace: / + * Node: dummy_node_and_some_suffix_added */ + ASSERT_STRNE(rcl_get_secure_root(TEST_NODE_NAME "_and_some_suffix_added", ROOT_NAMESPACE, + &allocator), + secure_root.c_str()); + putenv_wrapper(ROS_SECURITY_LOOKUP_TYPE_VAR_NAME "=MATCH_PREFIX"); + ASSERT_STREQ(rcl_get_secure_root(TEST_NODE_NAME "_and_some_suffix_added", ROOT_NAMESPACE, + &allocator), + secure_root.c_str()); } TEST(test_rcl_get_secure_root, nodeSecurityDirectoryOverride) { - rcl_allocator_t allocator = rcl_get_default_allocator(); - /* Specify a valid directory */ - putenv_wrapper(ROS_SECURITY_NODE_DIRECTORY_VAR_NAME "=" TEST_RESOURCES_DIRECTORY); - ASSERT_STREQ(rcl_get_secure_root("name shouldn't matter", "namespace shouldn't matter", &allocator), TEST_RESOURCES_DIRECTORY); + rcl_allocator_t allocator = rcl_get_default_allocator(); + /* Specify a valid directory */ + putenv_wrapper(ROS_SECURITY_NODE_DIRECTORY_VAR_NAME "=" TEST_RESOURCES_DIRECTORY); + ASSERT_STREQ(rcl_get_secure_root("name shouldn't matter", "namespace shouldn't matter", + &allocator), TEST_RESOURCES_DIRECTORY); - /* Setting root dir has no effect */ - putenv_wrapper(ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME "=" TEST_RESOURCES_DIRECTORY); - ASSERT_STREQ(rcl_get_secure_root("name shouldn't matter", "namespace shouldn't matter", &allocator), TEST_RESOURCES_DIRECTORY); + /* Setting root dir has no effect */ + putenv_wrapper(ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME "=" TEST_RESOURCES_DIRECTORY); + ASSERT_STREQ(rcl_get_secure_root("name shouldn't matter", "namespace shouldn't matter", + &allocator), TEST_RESOURCES_DIRECTORY); - /* The override provided should exist. Providing correct node/namespace/root dir won't help if the node override is invalid. */ - putenv_wrapper(ROS_SECURITY_NODE_DIRECTORY_VAR_NAME "=TheresN_oWayThi_sDirectory_Exists_hence_this_would_fail"); - ASSERT_EQ(rcl_get_secure_root(TEST_NODE_NAME, TEST_NODE_NAMESPACE, &allocator), - (char *) NULL); + /* The override provided should exist. Providing correct node/namespace/root dir won't help + * if the node override is invalid. */ + putenv_wrapper( + ROS_SECURITY_NODE_DIRECTORY_VAR_NAME + "=TheresN_oWayThi_sDirectory_Exists_hence_this_would_fail"); + ASSERT_EQ(rcl_get_secure_root(TEST_NODE_NAME, TEST_NODE_NAMESPACE, &allocator), + (char *) NULL); }