DDS Security dynamic plugin loading

Security plugin loading with the given configuration has been added.

The configuration can be given by either the Cyclone DDS configuration file or ParticipantQoS during participant creation.
ParticipantQoS is required by DDS Security spec. However, the configuration file is an additional useful feature that helps the user to add security to the DDS application without changing the binary.
If ParticipantQoS has a Property starting with the name "dds.sec", then the configuration file is ignored.

If the participant is the first participant, the security component is initialized. If the participant is the last active participant, then the security component is de-initialized.

Signed-off-by: Kurtulus Oksuztepe <kurtulus.oksuztepe@adlinktech.com>
This commit is contained in:
Kurtulus Oksuztepe 2019-11-20 16:54:28 +01:00 committed by eboasson
parent b561cb821f
commit b81ef4042b
43 changed files with 8709 additions and 615 deletions

View file

@ -74,10 +74,40 @@ set(CUnit_ddsc_config_simple_udp_uri "file://${CUnit_ddsc_config_simple_udp_file
set(CUnit_ddsc_config_simple_udp_max_participants "0")
set(CUnit_ddsc_config_simple_udp_env "${PROJECT_NAME_CAPS}_URI=${CUnit_ddsc_config_simple_udp_uri};MAX_PARTICIPANTS=${CUnit_ddsc_config_simple_udp_max_participants};${CUnit_ddsc_config_simple_udp_env}")
unset(test_lib_tests)
# Let the cunit application know the location and name of the security mock libraries.
#file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/../../../security/core/tests/plugin_loading" test_lib_native_dir)
file(TO_NATIVE_PATH "${PROJECT_BINARY_DIR}/src/security/core/tests/plugin_loading" test_lib_native_dir)
file(TO_NATIVE_PATH "/" test_lib_sep)
string(REPLACE "\\" "\\\\" test_lib_dir ${test_lib_native_dir})
string(REPLACE "\\" "\\\\" test_lib_sep ${test_lib_sep})
process_cunit_source_file("config.c" test_lib_header test_lib_suites test_lib_tests)
foreach(libtest ${test_lib_tests})
string(REPLACE ":" ";" libtest ${libtest})
list(GET libtest 0 suite)
list(GET libtest 1 test)
set(libtestname "CUnit_${suite}_${test}")
if("${CMAKE_HOST_SYSTEM}" MATCHES ".*Windows.*")
set_property(TEST ${libtestname} APPEND PROPERTY ENVIRONMENT "${test_lib_native_dir}")
else()
set_property(TEST ${libtestname} APPEND PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=${test_lib_native_dir};$ENV{LD_LIBRARY_PATH}")
endif()
endforeach()
set_tests_properties(
CUnit_ddsc_config_simple_udp
PROPERTIES
REQUIRED_FILES ${CUnit_ddsc_config_simple_udp_file}
ENVIRONMENT "${CUnit_ddsc_config_simple_udp_env}")
configure_file("config_env.h.in" "config_env.h")
configure_file("config_env.h.in" "config_env.h" @ONLY)

File diff suppressed because it is too large Load diff

View file

@ -14,5 +14,9 @@
#define CONFIG_ENV_SIMPLE_UDP "@CUnit_ddsc_config_simple_udp_uri@"
#define CONFIG_ENV_MAX_PARTICIPANTS "@CUnit_ddsc_config_simple_udp_max_participants@"
#define CONFIG_PLUGIN_MOCK_DIR "@test_lib_dir@"
#define CONFIG_LIB_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@"
#define CONFIG_LIB_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@"
#define CONFIG_LIB_SEP "@test_lib_sep@"
#endif /* CONFIG_ENV_H */

View file

@ -17,6 +17,10 @@
#include "dds/ddsi/q_globals.h"
#include "dds/ddsi/q_radmin.h"
#include "dds/ddsi/q_xmsg.h"
#include "dds/ddsrt/retcode.h"
#include "dds/ddsrt/types.h"
#include "dds/ddsrt/sync.h"
#if defined (__cplusplus)
extern "C" {
@ -30,6 +34,9 @@ typedef enum {
#ifdef DDSI_INCLUDE_SECURITY
#include "dds/security/dds_security_api.h"
#include "dds/security/core/dds_security_plugins.h"
typedef struct nn_msg_sec_info {
int64_t src_pp_handle;
int64_t dst_pp_handle;
@ -37,14 +44,7 @@ typedef struct nn_msg_sec_info {
} nn_msg_sec_info_t;
/**
* @brief Check if any participant has security enabled.
*
* @returns bool
* @retval true Some participant is secure
* @retval false No participant is not secure
*/
bool q_omg_security_enabled(void);
/**
* @brief Check if security is enabled for the participant.
@ -500,6 +500,30 @@ secure_conn_write(
bool dst_one,
nn_msg_sec_info_t *sec_info,
ddsi_tran_write_fn_t conn_write_cb);
/**
* @brief Loads the security plugins with the given configuration.
* This function tries to load the plugins only once. Returns the same
* result on subsequent calls.
* It logs the reason and returns error if can not load a plugin.
*
* @param[in] qos Participant qos which owns the Property list
* that contains security configurations and
* plugin properties that are required for loading libraries
* @returns dds_return_t
* @retval DDS_RETCODE_OK All plugins are successfully loaded
* @retval DDS_RETCODE_ERROR One or more security plugins are not loaded.
*/
dds_return_t q_omg_security_load( struct dds_security_context *security_context, const dds_qos_t *qos );
void q_omg_security_init( struct dds_security_context **sc);
void q_omg_security_deinit( struct dds_security_context **sc);
bool q_omg_is_security_loaded( struct dds_security_context *sc );
/**
* @brief Check if the participant and the proxy participant
@ -694,12 +718,6 @@ bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_
#include "dds/ddsi/q_unused.h"
inline bool
q_omg_security_enabled(void)
{
return false;
}
inline bool
q_omg_participant_is_secure(
UNUSED_ARG(const struct participant *pp))
@ -895,6 +913,17 @@ decode_rtps_message(
return NN_RTPS_MSG_STATE_PLAIN;
}
inline dds_return_t q_omg_security_load( UNUSED_ARG( struct dds_security_context *security_context ), UNUSED_ARG( const dds_qos_t *property_seq) )
{
return DDS_RETCODE_ERROR;
}
inline void q_omg_security_init( UNUSED_ARG( struct dds_security_context *sc) ) {}
inline void q_omg_security_deinit( UNUSED_ARG( struct dds_security_context *sc) ) {}
inline bool q_omg_is_security_loaded( UNUSED_ARG( struct dds_security_context *sc )) { return false; }
#endif /* DDSI_INCLUDE_SECURITY */
#if defined (__cplusplus)

View file

@ -220,6 +220,7 @@ struct participant
int64_t local_identity_handle; /* OMG DDS Security related member */
int64_t permissions_handle; /* OMG DDS Security related member */
struct participant_sec_attributes *sec_attr;
nn_security_info_t security_info;
#endif
};

View file

@ -46,6 +46,7 @@ struct ddsi_tran_factory;
struct ddsrt_thread_pool_s;
struct debug_monitor;
struct ddsi_tkmap;
struct dds_security_context;
typedef struct config_in_addr_node {
nn_locator_t loc;
@ -296,6 +297,12 @@ struct q_globals {
struct ddsi_builtin_topic_interface *builtin_topic_interface;
struct nn_group_membership *mship;
/* security globals */
#ifdef DDSI_INCLUDE_SECURITY
struct dds_security_context *security_context;
#endif
};
#if defined (__cplusplus)

View file

@ -321,21 +321,14 @@ DDS_EXPORT uint64_t nn_xqos_delta (const dds_qos_t *a, const dds_qos_t *b, uint6
DDS_EXPORT void nn_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted);
DDS_EXPORT void nn_log_xqos (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos);
DDS_EXPORT dds_qos_t *nn_xqos_dup (const dds_qos_t *src);
DDS_EXPORT bool nn_xqos_has_prop (const dds_qos_t *xqos, const char *pname, bool startswith);
DDS_EXPORT bool nn_xqos_has_prop (const dds_qos_t *xqos, const char *pname, bool startswith, bool check_non_empty);
#ifdef DDSI_INCLUDE_SECURITY
#define DDS_SEC_PROP_AUTH_IDENTITY_CA "dds.sec.auth.identity_ca"
#define DDS_SEC_PROP_AUTH_PRIV_KEY "dds.sec.auth.private_key"
#define DDS_SEC_PROP_AUTH_IDENTITY_CERT "dds.sec.auth.identity_certificate"
#define DDS_SEC_PROP_AUTH_PASSWORD "dds.sec.auth.password"
#define DDS_SEC_PROP_ACCESS_PERMISSIONS_CA "dds.sec.access.permissions_ca"
#define DDS_SEC_PROP_ACCESS_GOVERNANCE "dds.sec.access.governance"
#define DDS_SEC_PROP_ACCESS_PERMISSIONS "dds.sec.access.permissions"
#define DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR "dds.sec.auth.trusted_ca_dir"
struct omg_security_configuration_type;
DDS_EXPORT bool nn_xqos_mergein_security_config (dds_qos_t *xqos, const struct omg_security_configuration_type *cfg);
DDS_EXPORT void nn_xqos_mergein_security_config (dds_qos_t *xqos, const struct omg_security_configuration_type *cfg);
#endif
#if defined (__cplusplus)

View file

@ -20,12 +20,43 @@
#include "dds/ddsrt/process.h"
#include "dds/ddsi/q_bswap.h"
#include "dds/ddsi/q_unused.h"
#include "dds/ddsi/q_radmin.h"
#include "dds/ddsi/ddsi_entity_index.h"
#include "dds/ddsi/ddsi_security_omg.h"
#include "dds/ddsi/ddsi_sertopic.h"
#include "dds/ddsi/q_config.h"
#include "dds/ddsi/q_log.h"
#include "dds/ddsrt/sync.h"
#include "dds/security/dds_security_api.h"
#include "dds/security/core/dds_security_utils.h"
#include "dds/security/core/dds_security_plugins.h"
#include "dds/ddsrt/hopscotch.h"
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/q_xevent.h"
#include "dds/ddsi/q_plist.h"
#define AUTH_NAME "Authentication"
#define AC_NAME "Access Control"
#define CRYPTO_NAME "Cryptographic"
#define SECURITY_EXCEPTION_INIT {NULL, 0, 0}
struct dds_security_context {
dds_security_plugin auth_plugin;
dds_security_plugin ac_plugin;
dds_security_plugin crypto_plugin;
dds_security_authentication *authentication_context;
dds_security_cryptography *crypto_context;
dds_security_access_control *access_control_context;
ddsrt_mutex_t omg_security_lock;
uint32_t next_plugin_id;
};
typedef struct dds_security_context dds_security_context;
static bool
@ -34,6 +65,7 @@ q_omg_writer_is_payload_protected(
static bool endpoint_is_DCPSParticipantSecure(const ddsi_guid_t *guid)
{
return ((guid->entityid.u == NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER) ||
@ -76,11 +108,209 @@ static bool endpoint_is_DCPSParticipantVolatileMessageSecure(const ddsi_guid_t *
#endif
}
bool q_omg_is_security_loaded( dds_security_context *sc ){
if( sc->crypto_context == NULL && sc->authentication_context == NULL && sc->access_control_context == NULL){
return false;
} else {
return true;
}
}
bool
q_omg_security_enabled(void)
void q_omg_security_init( dds_security_context **sc )
{
return false;
*sc = ddsrt_malloc( sizeof( dds_security_context));
memset( *sc, 0, sizeof( dds_security_context));
//if( participant_reference_count == 0 ){
(*sc)->auth_plugin.name = AUTH_NAME;
(*sc)->ac_plugin.name = AC_NAME;
(*sc)->crypto_plugin.name = CRYPTO_NAME;
(void)ddsrt_mutex_init(&(*sc)->omg_security_lock);
DDS_LOG(DDS_LC_TRACE,"DDS Security init\n");
#if HANDSHAKE_IMPLEMENTED
//remote_participant_crypto_handle_list_init();
#endif
//}
//participant_reference_count++;
}
/**
* Releases all plugins
*/
static void release_plugins( dds_security_context *security_context )
{
#if HANDSHAKE_IMPLEMENTED
q_handshake_terminate();
#endif
if (dds_security_plugin_release( &security_context->auth_plugin, security_context->authentication_context )) {
DDS_ERROR("Error occured releasing %s plugin", security_context->auth_plugin.name);
}
if (dds_security_plugin_release( &security_context->crypto_plugin, security_context->crypto_context )) {
DDS_ERROR("Error occured releasing %s plugin", security_context->crypto_plugin.name);
}
if (dds_security_plugin_release( &security_context->ac_plugin, security_context->access_control_context )) {
DDS_ERROR("Error occured releasing %s plugin", security_context->ac_plugin.name);
}
security_context->authentication_context = NULL;
security_context->access_control_context = NULL;
security_context->crypto_context = NULL;
}
void q_omg_security_deinit( struct dds_security_context **security_context) {
assert( security_context != NULL );
assert( *security_context != NULL );
#if HANDSHAKE_IMPLEMENTED
//remote_participant_crypto_handle_list_deinit();
#endif
if( (*security_context)->authentication_context != NULL && (*security_context)->access_control_context != NULL && (*security_context)->crypto_context != NULL ){
release_plugins( *security_context );
}
ddsrt_mutex_destroy(&(*security_context)->omg_security_lock);
ddsrt_free( *security_context );
*security_context = NULL;
DDS_LOG(DDS_LC_TRACE,"DDS Security deinit\n");
}
static void
dds_qos_to_security_plugin_configuration(
const dds_qos_t *qos,
dds_security_plugin_suite_config *suite_config)
{
uint32_t i;
#define CHECK_SECURITY_PROPERTY( security_property, target ) \
if(strcmp (qos->property.value.props[i].name, security_property) == 0){ \
target = ddsrt_strdup( qos->property.value.props[i].value ); \
}
for (i = 0; i < qos->property.value.n; i++) {
CHECK_SECURITY_PROPERTY( DDS_SEC_PROP_AUTH_LIBRARY_PATH, suite_config->authentication.library_path )
else CHECK_SECURITY_PROPERTY( DDS_SEC_PROP_AUTH_LIBRARY_INIT, suite_config->authentication.library_init )
else CHECK_SECURITY_PROPERTY( DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, suite_config->authentication.library_finalize )
else CHECK_SECURITY_PROPERTY( DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, suite_config->cryptography.library_path )
else CHECK_SECURITY_PROPERTY( DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, suite_config->cryptography.library_init )
else CHECK_SECURITY_PROPERTY( DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, suite_config->cryptography.library_finalize )
else CHECK_SECURITY_PROPERTY( DDS_SEC_PROP_ACCESS_LIBRARY_PATH, suite_config->access_control.library_path )
else CHECK_SECURITY_PROPERTY( DDS_SEC_PROP_ACCESS_LIBRARY_INIT, suite_config->access_control.library_init )
else CHECK_SECURITY_PROPERTY( DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, suite_config->access_control.library_finalize )
}
#undef CHECK_SECURITY_PROPERTY
}
static void deinit_plugin_config(dds_security_plugin_config *plugin_config){
ddsrt_free( plugin_config->library_path );
ddsrt_free( plugin_config->library_init );
ddsrt_free( plugin_config->library_finalize );
}
static void deinit_plugin_suite_config(dds_security_plugin_suite_config *suite_config ){
deinit_plugin_config( &suite_config->access_control );
deinit_plugin_config( &suite_config->authentication );
deinit_plugin_config( &suite_config->cryptography );
}
dds_return_t q_omg_security_load( dds_security_context *security_context,
const dds_qos_t *qos)
{
dds_return_t ret = DDS_RETCODE_ERROR;
ddsrt_mutex_lock(&security_context->omg_security_lock);
dds_security_plugin_suite_config plugin_suite_config;
memset ( &plugin_suite_config, 0, sizeof(dds_security_plugin_suite_config));
/* Get plugin information */
dds_qos_to_security_plugin_configuration( qos, &plugin_suite_config);
/* Check configuration content */
if( dds_security_check_plugin_configuration( &plugin_suite_config ) == DDS_RETCODE_OK ){
if (dds_security_load_security_library(
&(plugin_suite_config.authentication), &security_context->auth_plugin,
(void**) &security_context->authentication_context) == DDS_RETCODE_OK) {
if (dds_security_load_security_library(
&(plugin_suite_config.access_control), &security_context->ac_plugin,
(void**) &security_context->access_control_context) == DDS_RETCODE_OK ) {
if (dds_security_load_security_library(
&(plugin_suite_config.cryptography), &security_context->crypto_plugin,
(void**) &security_context->crypto_context) == DDS_RETCODE_OK ) {
/* now check if all plugin functions are implemented */
if( dds_security_verify_plugin_functions(
security_context->authentication_context,&security_context->auth_plugin,
security_context->crypto_context,&security_context->crypto_plugin,
security_context->access_control_context, &security_context->ac_plugin) == DDS_RETCODE_OK){
/* Add listeners */
#if LISTENERS_IMPLEMENTED
if ( access_control_context->set_listener(access_control_context, &listener_ac, &ex)) {
if ( authentication_context->set_listener(authentication_context, &listener_auth, &ex)) {
#if HANDSHAKE_IMPLEMENTED
(void)q_handshake_initialize();
#endif
} else {
DDS_ERROR("Could not set authentication listener: %s\n",
ex.message ? ex.message : "<unknown error>");
}
} else {
DDS_ERROR("Could not set access_control listener: %s\n",
ex.message ? ex.message : "<unknown error>");
}
#endif //LISTENERS_IMPLEMENTED
//tried_to_load = true;
//ret = last_load_result = DDS_RETCODE_OK;
ret = DDS_RETCODE_OK;
//omg_security_plugin_loaded = true;
DDS_INFO( "DDS Security plugins have been loaded\n" );
} else {
release_plugins( security_context );
}
} else{
DDS_ERROR("Could not load %s library\n", security_context->crypto_plugin.name);
}
}else{
DDS_ERROR("Could not load %s library\n", security_context->ac_plugin.name);
}
}
else{
DDS_ERROR("Could not load %s plugin.\n", security_context->auth_plugin.name);
}
}
deinit_plugin_suite_config( &plugin_suite_config );
ddsrt_mutex_unlock( &security_context->omg_security_lock );
return ret;
}
bool
@ -797,53 +1027,54 @@ encode_datareader_submsg(
struct proxy_writer *pwr,
const struct ddsi_guid *rd_guid)
{
struct reader *rd = entidx_lookup_reader_guid(pwr->e.gv->entity_index, rd_guid);
struct participant *pp = NULL;
/* Only encode when needed. */
if (q_omg_security_enabled())
if( rd != NULL ){
pp = rd->c.pp;
}
if (!pp && q_omg_participant_is_secure( pp ))
{
struct reader *rd = entidx_lookup_reader_guid(pwr->e.gv->entity_index, rd_guid);
if (rd)
if (q_omg_reader_is_submessage_protected(rd))
{
if (q_omg_reader_is_submessage_protected(rd))
unsigned char *src_buf;
unsigned int src_len;
unsigned char *dst_buf;
unsigned int dst_len;
/* Make one blob of the current sub-message by appending the serialized payload. */
nn_xmsg_submsg_append_refd_payload(msg, sm_marker);
/* Get the sub-message buffer. */
src_buf = (unsigned char*)nn_xmsg_submsg_from_marker(msg, sm_marker);
src_len = (unsigned int)nn_xmsg_submsg_size(msg, sm_marker);
/* Do the actual encryption. */
if (q_omg_security_encode_datareader_submessage(rd, &(pwr->e.guid.prefix), src_buf, src_len, &dst_buf, &dst_len))
{
unsigned char *src_buf;
unsigned int src_len;
unsigned char *dst_buf;
unsigned int dst_len;
/* Make one blob of the current sub-message by appending the serialized payload. */
nn_xmsg_submsg_append_refd_payload(msg, sm_marker);
/* Get the sub-message buffer. */
src_buf = (unsigned char*)nn_xmsg_submsg_from_marker(msg, sm_marker);
src_len = (unsigned int)nn_xmsg_submsg_size(msg, sm_marker);
/* Do the actual encryption. */
if (q_omg_security_encode_datareader_submessage(rd, &(pwr->e.guid.prefix), src_buf, src_len, &dst_buf, &dst_len))
{
/* Replace the old sub-message with the new encoded one(s). */
nn_xmsg_submsg_replace(msg, sm_marker, dst_buf, dst_len);
ddsrt_free(dst_buf);
}
else
{
/* The sub-message should have been encoded, which failed.
* Remove it to prevent it from being send. */
nn_xmsg_submsg_remove(msg, sm_marker);
}
/* Replace the old sub-message with the new encoded one(s). */
nn_xmsg_submsg_replace(msg, sm_marker, dst_buf, dst_len);
ddsrt_free(dst_buf);
}
else
{
/* The sub-message should have been encoded, which failed.
* Remove it to prevent it from being send. */
nn_xmsg_submsg_remove(msg, sm_marker);
}
}
}
}
void
encode_datawriter_submsg(
struct nn_xmsg *msg,
struct nn_xmsg_marker sm_marker,
struct writer *wr)
{
struct participant *pp = wr->c.pp;
/* Only encode when needed. */
if (q_omg_security_enabled())
if (q_omg_participant_is_secure( pp ))
{
if (q_omg_writer_is_submessage_protected(wr))
{

View file

@ -698,44 +698,77 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *
nn_plist_mergein_missing (pp->plist, &gv->default_local_plist_pp, ~(uint64_t)0, ~(uint64_t)0);
#ifdef DDSI_INCLUDE_SECURITY
if (gv->config.omg_security_configuration)
/*
* if there there are security properties check them .
* if there are no security properties, then merge from security configuration if there is
*/
/* check for existing security properties (name starts with dds.sec. conform DDS Security spec 7.2.4.1)
* and return if any is found */
{
/* For security, configuration can be provided through the configuration.
* However, the specification (and the plugins) expect it to be in the QoS. */
if (!nn_xqos_mergein_security_config(&pp->plist->qos, &gv->config.omg_security_configuration->cfg))
{
char *req[] = { DDS_SEC_PROP_AUTH_IDENTITY_CA,
DDS_SEC_PROP_AUTH_PRIV_KEY,
DDS_SEC_PROP_AUTH_IDENTITY_CERT,
DDS_SEC_PROP_ACCESS_PERMISSIONS_CA,
DDS_SEC_PROP_ACCESS_GOVERNANCE,
DDS_SEC_PROP_ACCESS_PERMISSIONS };
bool ready_to_load_security = false;
if (nn_xqos_has_prop(&pp->plist->qos, "dds.sec.", true, false)) {
char *req[] = {DDS_SEC_PROP_AUTH_IDENTITY_CA,
DDS_SEC_PROP_AUTH_PRIV_KEY,
DDS_SEC_PROP_AUTH_IDENTITY_CERT,
DDS_SEC_PROP_ACCESS_PERMISSIONS_CA,
DDS_SEC_PROP_ACCESS_GOVERNANCE,
DDS_SEC_PROP_ACCESS_PERMISSIONS,
GVLOGDISC ("new_participant("PGUIDFMT"): using security settings from QoS, ignoring security configuration\n", PGUID (*ppguid));
DDS_SEC_PROP_AUTH_LIBRARY_PATH,
DDS_SEC_PROP_AUTH_LIBRARY_INIT,
DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE,
DDS_SEC_PROP_CRYPTO_LIBRARY_PATH,
DDS_SEC_PROP_CRYPTO_LIBRARY_INIT,
DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE,
DDS_SEC_PROP_ACCESS_LIBRARY_PATH,
DDS_SEC_PROP_ACCESS_LIBRARY_INIT,
DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE};
GVLOGDISC ("new_participant("
PGUIDFMT
"): using security settings from QoS\n", PGUID(*ppguid));
/* check if all required security properties exist in qos */
for (size_t i = 0; i < sizeof(req) / sizeof(req[0]); i++)
{
if (!nn_xqos_has_prop (&pp->plist->qos, req[i], false))
{
GVERROR ("new_participant("PGUIDFMT"): required security property %s missing in Property QoS\n", PGUID (*ppguid), req[i]);
for (size_t i = 0; i < sizeof(req) / sizeof(req[0]); i++) {
if (!nn_xqos_has_prop(&pp->plist->qos, req[i], false, true)) {
GVERROR ("new_participant("
PGUIDFMT
"): required security property %s missing in Property QoS\n", PGUID(*ppguid), req[i]);
ret = DDS_RETCODE_PRECONDITION_NOT_MET;
}
}
if (ret != DDS_RETCODE_OK)
if (ret == DDS_RETCODE_OK) {
ready_to_load_security = true;
} else {
goto new_pp_err_secprop;
}
} else if (gv->config.omg_security_configuration) {
/* For security, configuration can be provided through the configuration.
* However, the specification (and the plugins) expect it to be in the QoS. */
GVLOGDISC ("new_participant("
PGUIDFMT
"): using security settings from configuration\n", PGUID(*ppguid));
nn_xqos_mergein_security_config(&pp->plist->qos, &gv->config.omg_security_configuration->cfg);
ready_to_load_security = true;
}
if( q_omg_is_security_loaded( gv->security_context ) == false ){
if (ready_to_load_security && q_omg_security_load(gv->security_context, &pp->plist->qos) < 0) {
GVERROR("Could not load security\n");
ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
goto new_pp_err_secprop;
}
} else {
GVLOGDISC ("new_participant("
PGUIDFMT
"): security is already loaded for this domain\n", PGUID(*ppguid));
}
}
if (nn_xqos_has_prop (&pp->plist->qos, "dds.sec.", true))
{
if (!q_omg_security_check_create_participant (pp, gv->config.domainId))
{
ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
goto not_allowed;
}
}
#endif
if (gv->logconfig.c.mask & DDS_LC_DISCOVERY)

View file

@ -62,6 +62,8 @@
#include "dds__whc.h"
#include "dds/ddsi/ddsi_iid.h"
#include "dds/ddsi/ddsi_security_omg.h"
static void add_peer_addresses (const struct q_globals *gv, struct addrset *as, const struct config_peer_listelem *list)
{
while (list)
@ -1081,6 +1083,8 @@ int rtps_init (struct q_globals *gv)
* the entities (see DDS Security spec chapter 8.8.8.1). */
add_property_to_xqos(&gv->builtin_volatile_xqos_rd, "dds.sec.builtin_endpoint_name", "BuiltinParticipantVolatileMessageSecureReader");
add_property_to_xqos(&gv->builtin_volatile_xqos_wr, "dds.sec.builtin_endpoint_name", "BuiltinParticipantVolatileMessageSecureWriter");
q_omg_security_init( &gv->security_context );
#endif
make_special_topics (gv);
@ -1420,6 +1424,8 @@ err_unicast_sockets:
nn_xqos_fini (&gv->builtin_stateless_xqos_rd);
nn_xqos_fini (&gv->builtin_volatile_xqos_wr);
nn_xqos_fini (&gv->builtin_volatile_xqos_rd);
q_omg_security_deinit( &gv->security_context );
#endif
nn_xqos_fini (&gv->builtin_endpoint_xqos_wr);
nn_xqos_fini (&gv->builtin_endpoint_xqos_rd);
@ -1764,6 +1770,8 @@ void rtps_fini (struct q_globals *gv)
nn_xqos_fini (&gv->builtin_stateless_xqos_rd);
nn_xqos_fini (&gv->builtin_volatile_xqos_wr);
nn_xqos_fini (&gv->builtin_volatile_xqos_rd);
q_omg_security_deinit( &gv->security_context);
#endif
nn_xqos_fini (&gv->builtin_endpoint_xqos_wr);
nn_xqos_fini (&gv->builtin_endpoint_xqos_rd);

View file

@ -40,6 +40,7 @@
#include "dds/ddsi/q_misc.h" /* for vendor_is_... */
#include "dds/ddsi/ddsi_plist_generic.h"
#include "dds/ddsi/ddsi_security_omg.h"
/* I am tempted to change LENGTH_UNLIMITED to 0 in the API (with -1
supported for backwards compatibility) ... on the wire however
@ -2884,17 +2885,17 @@ dds_qos_t * nn_xqos_dup (const dds_qos_t *src)
return dst;
}
bool nn_xqos_has_prop (const dds_qos_t *xqos, const char *pname, bool startswith)
bool nn_xqos_has_prop (const dds_qos_t *xqos, const char *pname, bool startswith, bool check_non_empty)
{
if (!(xqos->present & QP_PROPERTY_LIST))
return false;
for (uint32_t i = 0; i < xqos->property.value.n; i++)
{
if (startswith && (strncmp (xqos->property.value.props[i].name, pname, strlen (pname)) == 0))
return true;
else if (!startswith && (strcmp (xqos->property.value.props[i].name, pname) == 0))
return true;
for (uint32_t i = 0; i < xqos->property.value.n; i++) {
if (startswith && (strncmp(xqos->property.value.props[i].name, pname, strlen(pname)) == 0)) {
return !check_non_empty || strlen(xqos->property.value.props[i].value) != 0;
} else if (!startswith && (strcmp(xqos->property.value.props[i].name, pname) == 0)) {
return !check_non_empty || strlen(xqos->property.value.props[i].value) != 0;
}
}
return false;
}
@ -2912,7 +2913,7 @@ static void fill_property(dds_property_t *prop, const char *name, const char *va
* plugins to get their proper settings. If security properties are already present in
* the QoS, the settings from configuration are ignored.
*/
bool nn_xqos_mergein_security_config (dds_qos_t *xqos, const struct omg_security_configuration_type *cfg)
void nn_xqos_mergein_security_config (dds_qos_t *xqos, const struct omg_security_configuration_type *cfg)
{
assert(cfg != NULL);
@ -2925,24 +2926,29 @@ bool nn_xqos_mergein_security_config (dds_qos_t *xqos, const struct omg_security
xqos->present |= QP_PROPERTY_LIST;
}
/* check for existing security properties (name starts with dds.sec. conform DDS Security spec 7.2.4.1)
* and return if any is found */
if (nn_xqos_has_prop (xqos, "dds.sec.", true))
return false;
/* assume that no security properties exist in qos: fill QoS properties with values from configuration */
xqos->property.value.props = ddsrt_realloc (xqos->property.value.props, xqos->property.value.n + 18 /* max */ * sizeof (dds_property_t));
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_AUTH_LIBRARY_PATH, cfg->authentication_plugin.library_path);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_AUTH_LIBRARY_INIT, cfg->authentication_plugin.library_init);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, cfg->authentication_plugin.library_finalize);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, cfg->cryptography_plugin.library_path);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, cfg->cryptography_plugin.library_init);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, cfg->cryptography_plugin.library_finalize);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_ACCESS_LIBRARY_PATH, cfg->access_control_plugin.library_path);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_ACCESS_LIBRARY_INIT, cfg->access_control_plugin.library_init);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, cfg->access_control_plugin.library_finalize);
/* no security properties exist in qos: fill QoS properties with values from configuration */
xqos->property.value.props = ddsrt_realloc (xqos->property.value.props, xqos->property.value.n + 8 /* max */ * sizeof (dds_property_t));
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_AUTH_IDENTITY_CA, cfg->authentication_properties.identity_ca);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_AUTH_PRIV_KEY, cfg->authentication_properties.private_key);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_AUTH_IDENTITY_CERT, cfg->authentication_properties.identity_certificate);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, cfg->access_control_properties.permissions_ca);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_ACCESS_GOVERNANCE, cfg->access_control_properties.governance);
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_ACCESS_PERMISSIONS, cfg->access_control_properties.permissions);
if (cfg->authentication_properties.password && (strlen(cfg->authentication_properties.password) != 0))
if (cfg->authentication_properties.password )
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_AUTH_PASSWORD, cfg->authentication_properties.password);
if (cfg->authentication_properties.trusted_ca_dir && (strlen(cfg->authentication_properties.trusted_ca_dir) != 0))
if (cfg->authentication_properties.trusted_ca_dir )
fill_property(&(xqos->property.value.props[xqos->property.value.n++]), DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, cfg->authentication_properties.trusted_ca_dir);
return true;
}
#endif /* DDSI_INCLUDE_SECURITY */

View file

@ -977,12 +977,9 @@ static void handle_xevk_acknack (struct nn_xpack *xp, struct xevent *ev, nn_mtim
seqno_t nack_seq;
struct participant *pp = NULL;
if (q_omg_security_enabled())
{
struct reader *rd = entidx_lookup_reader_guid(pwr->e.gv->entity_index, &ev->u.acknack.rd_guid);
if (rd)
pp = rd->c.pp;
}
struct reader *rd = entidx_lookup_reader_guid(pwr->e.gv->entity_index, &ev->u.acknack.rd_guid);
if (rd)
pp = rd->c.pp;
if ((msg = nn_xmsg_new (gv->xmsgpool, &ev->u.acknack.rd_guid, pp, ACKNACK_SIZE_MAX, NN_XMSG_KIND_CONTROL)) == NULL)
goto outofmem;