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:
parent
b561cb821f
commit
b81ef4042b
43 changed files with 8709 additions and 615 deletions
|
@ -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
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue