Skip to content

Commit

Permalink
Add context name and namespace, allow configuring security directory …
Browse files Browse the repository at this point in the history
…with context name

Signed-off-by: Ivan Santiago Paunovic <[email protected]>
  • Loading branch information
ivanpauno committed Jan 24, 2020
1 parent 48c08d6 commit c271082
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 123 deletions.
29 changes: 16 additions & 13 deletions rcl/include/rcl/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,30 +69,33 @@ RCL_PUBLIC
rcl_ret_t
rcl_get_enforcement_policy(rmw_security_enforcement_policy_t * policy);

/// Return the secure root directory associated with a node given its validated name and namespace.
/// Return the secure root given a 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
* The returned security directory is associated with the node or context depending on the
* rmw implementation.
*
* E.g. for a node/context 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/context 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.
* variable (only in rmw implementations that associate a security directory with a node),
* allowing users to explicitly specify the exact secure root directory to be utilized.
* Such an override is useful for where the FQN of a node is non-deterministic before runtime,
* or when testing and using additional tools that may not otherwise be easily provisioned.
*
* \param[in] node_name validated node name (a single token)
* \param[in] node_namespace validated, absolute namespace (starting with "/")
* \param[in] name validated node name (a single token)
* \param[in] namespace_ validated, absolute namespace (starting with "/")
* \param[in] allocator the allocator to use for allocation
* \returns machine specific (absolute) node secure root path or NULL on failure
* returned pointer must be deallocated by the caller of this function
* \returns Machine specific (absolute) node secure root path or NULL on failure.
* Returned pointer must be deallocated by the caller of this function
*/
RCL_PUBLIC
char * rcl_get_secure_root(
const char * node_name,
const char * node_namespace,
const rcl_allocator_t * allocator
);
const char * name,
const char * namespace_,
const rcl_allocator_t * allocator);

#ifdef __cplusplus
}
Expand Down
58 changes: 39 additions & 19 deletions rcl/src/rcl/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ extern "C"
#include "rcutils/logging_macros.h"
#include "rcutils/stdatomic_helper.h"
#include "rmw/error_handling.h"
#include "rmw/security.h"
#include "tracetools/tracetools.h"

static atomic_uint_least64_t __rcl_next_unique_id = ATOMIC_VAR_INIT(1);
Expand Down Expand Up @@ -159,25 +160,44 @@ rcl_init(
}

// TODO(ivanpauno): Uncomment this when new path discovery magic is ready.
// bool use_security = false;
// ret = rcl_use_security(&use_security);
// if (RCL_RET_OK != ret) {
// fail_ret = ret;
// goto fail;
// }
// RCUTILS_LOG_DEBUG_NAMED(
// ROS_PACKAGE_NAME, "Using security: %s", use_security ? "true" : "false");

// ret = rcl_get_enforcement_policy(
// &context->impl->init_options.impl->rmw_init_options.security_options.enforce_security);
// if (RCL_RET_OK != ret) {
// fail_ret = ret;
// goto fail;
// }

// if (use_security) {
// ...
// }
bool use_security = false;
ret = rcl_use_security(&use_security);
if (RCL_RET_OK != ret) {
fail_ret = ret;
goto fail;
}
RCUTILS_LOG_DEBUG_NAMED(
ROS_PACKAGE_NAME, "Using security: %s", use_security ? "true" : "false");

if (!rmw_use_node_name_in_security_directory_lookup()) {
rmw_security_options_t * security_options =
&context->impl->init_options.impl->rmw_init_options.security_options;

ret = rcl_get_enforcement_policy(&security_options->enforce_security);
if (RCL_RET_OK != ret) {
fail_ret = ret;
goto fail;
}

if (!use_security) {
security_options->enforce_security = RMW_SECURITY_ENFORCEMENT_PERMISSIVE;
} else { // if use_security
// File discovery magic here
char * secure_root = rcl_get_secure_root(
options->impl->rmw_init_options.name,
options->impl->rmw_init_options.namespace_,
&options->impl->allocator);
if (secure_root) {
RCUTILS_LOG_INFO_NAMED(ROS_PACKAGE_NAME, "Found security directory: %s", secure_root);
security_options->security_root_path = secure_root;
} else {
if (RMW_SECURITY_ENFORCEMENT_ENFORCE == security_options->enforce_security) {
ret = RCL_RET_ERROR;
goto fail;
}
}
}
}

// Initialize rmw_init.
rmw_ret_t rmw_ret = rmw_init(
Expand Down
58 changes: 31 additions & 27 deletions rcl/src/rcl/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ extern "C"
#include "rmw/error_handling.h"
#include "rmw/security_options.h"
#include "rmw/rmw.h"
#include "rmw/security.h"
#include "rmw/validate_namespace.h"
#include "rmw/validate_node_name.h"
#include "tracetools/tracetools.h"
Expand Down Expand Up @@ -264,34 +265,37 @@ rcl_node_init(

rmw_security_options_t node_security_options =
rmw_get_zero_initialized_security_options();
rmw_security_options_t * node_security_options_ptr = NULL;
if (rmw_use_node_name_in_security_directory_lookup()) {
node_security_options_ptr = &node_security_options;
bool use_security;
ret = rcl_use_security(&use_security);
if (RCL_RET_OK != ret) {
fail_ret = ret;
goto fail;
}
RCUTILS_LOG_DEBUG_NAMED(
ROS_PACKAGE_NAME, "Using security: %s", use_security ? "true" : "false");

bool use_security;
ret = rcl_use_security(&use_security);
if (RCL_RET_OK != ret) {
fail_ret = ret;
goto fail;
}
RCUTILS_LOG_DEBUG_NAMED(
ROS_PACKAGE_NAME, "Using security: %s", use_security ? "true" : "false");

ret = rcl_get_enforcement_policy(&node_security_options.enforce_security);
if (RCL_RET_OK != ret) {
fail_ret = ret;
goto fail;
}
ret = rcl_get_enforcement_policy(&node_security_options.enforce_security);
if (RCL_RET_OK != ret) {
fail_ret = ret;
goto fail;
}

if (!use_security) {
node_security_options.enforce_security = RMW_SECURITY_ENFORCEMENT_PERMISSIVE;
} else { // if use_security
// File discovery magic here
node_secure_root = rcl_get_secure_root(name, local_namespace_, allocator);
if (node_secure_root) {
RCUTILS_LOG_INFO_NAMED(ROS_PACKAGE_NAME, "Found security directory: %s", node_secure_root);
node_security_options.security_root_path = node_secure_root;
} else {
if (RMW_SECURITY_ENFORCEMENT_ENFORCE == node_security_options.enforce_security) {
ret = RCL_RET_ERROR;
goto cleanup;
if (!use_security) {
node_security_options.enforce_security = RMW_SECURITY_ENFORCEMENT_PERMISSIVE;
} else { // if use_security
// File discovery magic here
node_secure_root = rcl_get_secure_root(name, local_namespace_, allocator);
if (node_secure_root) {
RCUTILS_LOG_INFO_NAMED(ROS_PACKAGE_NAME, "Found security directory: %s", node_secure_root);
node_security_options.security_root_path = node_secure_root;
} else {
if (RMW_SECURITY_ENFORCEMENT_ENFORCE == node_security_options.enforce_security) {
ret = RCL_RET_ERROR;
goto cleanup;
}
}
}
}
Expand All @@ -302,7 +306,7 @@ rcl_node_init(

node->impl->rmw_node_handle = rmw_create_node(
&(node->context->impl->rmw_context),
name, local_namespace_, domain_id, &node_security_options, localhost_only);
name, local_namespace_, domain_id, node_security_options_ptr, localhost_only);

RCL_CHECK_FOR_NULL_WITH_MSG(
node->impl->rmw_node_handle, rmw_get_error_string().str, goto fail);
Expand Down
36 changes: 17 additions & 19 deletions rcl/src/rcl/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@
#include <stdbool.h>

#include "rcl/error_handling.h"

#include "rcutils/filesystem.h"
#include "rcutils/get_env.h"
#include "rcutils/format_string.h"
#include "rcutils/get_env.h"
#include "rcutils/strdup.h"

#include "rmw/security.h"
#include "rmw/security_options.h"

#ifdef __clang__
Expand Down Expand Up @@ -227,50 +231,44 @@ char * rcl_get_secure_root(
const rcl_allocator_t * allocator)
{
bool ros_secure_node_override = true;
bool use_node_name_in_lookup = rmw_use_node_name_in_security_directory_lookup();

// find out if either of the configuration environment variables are set
const char * env_buf = NULL;
if (NULL == node_name) {
return NULL;
}
if (rcutils_get_env(ROS_SECURITY_NODE_DIRECTORY_VAR_NAME, &env_buf)) {
return NULL;
}
if (!env_buf) {
return NULL;
if (use_node_name_in_lookup) {
if (rcutils_get_env(ROS_SECURITY_NODE_DIRECTORY_VAR_NAME, &env_buf)) {
return NULL;
}
if (!env_buf) {
return NULL;
}
}
size_t ros_secure_root_size = strlen(env_buf);
if (!ros_secure_root_size) {
if (!use_node_name_in_lookup || 0 == strcmp("", env_buf)) {
// check root directory if node directory environment variable is empty
if (rcutils_get_env(ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME, &env_buf)) {
return NULL;
}
if (!env_buf) {
return NULL;
}
ros_secure_root_size = strlen(env_buf);
if (!ros_secure_root_size) {
if (0 == strcmp("", env_buf)) {
return NULL; // environment variable was empty
} else {
ros_secure_node_override = false;
}
}

// found a usable environment variable, copy into our memory before overwriting with next lookup
char * ros_secure_root_env =
(char *)allocator->allocate(ros_secure_root_size + 1, allocator->state);
memcpy(ros_secure_root_env, env_buf, ros_secure_root_size + 1);
// 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.
char * ros_secure_root_env = rcutils_strdup(env_buf, *allocator);

char * lookup_strategy = NULL;
char * node_secure_root = 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);
node_secure_root = rcutils_strdup(ros_secure_root_env, *allocator);
lookup_strategy = g_security_lookup_type_strings[ROS_SECURITY_LOOKUP_NODE_OVERRIDE];

} else {
// Check which lookup method to use and invoke the relevant function.
const char * ros_security_lookup_type = NULL;
Expand Down
Loading

0 comments on commit c271082

Please sign in to comment.