Added DDS Security XML configuration elements. (#268)

* Added DDS Security XML configuration elements.

Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>

* Extended security configuration tests.

Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>

* Updated security conf to qos conversion.

Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>
This commit is contained in:
martinbremmer 2019-10-11 15:43:30 +02:00 committed by eboasson
parent ef90c11e8d
commit 7c1e47218d
8 changed files with 650 additions and 2 deletions

View file

@ -54,7 +54,8 @@ set(ddsc_test_sources
add_cunit_executable(cunit_ddsc ${ddsc_test_sources})
target_include_directories(
cunit_ddsc PRIVATE
"$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/src/include/>")
"$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/src/include/>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../ddsi/include/>")
target_link_libraries(cunit_ddsc PRIVATE RoundTrip Space TypesArrayKey ddsc)
# Setup environment for config-tests

View file

@ -19,6 +19,7 @@
#include "dds/ddsrt/cdtors.h"
#include "dds/ddsrt/environ.h"
#include "dds/ddsrt/heap.h"
#include "dds/ddsi/q_misc.h"
#define FORCE_ENV
@ -118,3 +119,384 @@ CU_Test(ddsc_config, incorrect_config, .init = ddsrt_init, .fini = ddsrt_fini) {
"</"DDS_PROJECT_NAME">") == DDS_RETCODE_OK);
CU_ASSERT_FATAL(dds_create_domain(2, "") == DDS_RETCODE_PRECONDITION_NOT_MET);
}
/*
* The 'found' variable will contain flags related to the expected log
* messages that were received.
* Using flags will allow to show that when message isn't received,
* which one it was.
*/
static uint32_t found;
static void logger(void *ptr, const dds_log_data_t *data)
{
char **expected = (char**)ptr;
for (uint32_t i = 0; expected[i] != NULL; i++) {
if (ddsi2_patmatch(expected[i], data->message)) {
found |= (uint32_t)(1 << i);
}
}
}
CU_Test(ddsc_config, security_non, .init = ddsrt_init, .fini = ddsrt_fini) {
/* There shouldn't be traces that mention security. */
const char *log_expected[] = {
"*Security*",
NULL
};
dds_entity_t participant;
/* Set up the trace sinks to detect the config parsing. */
dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG);
dds_set_log_sink(&logger, (void*)log_expected);
dds_set_trace_sink(&logger, (void*)log_expected);
/* Create participant with an empty security element. */
found = 0;
ddsrt_setenv(URI_VARIABLE, "<Tracing><Verbosity>finest</></>");
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
ddsrt_setenv(URI_VARIABLE, "");
CU_ASSERT_FATAL(participant > 0);
dds_delete(participant);
/* No security traces should have been provided. */
CU_ASSERT_FATAL(found == 0x0);
}
CU_Test(ddsc_config, security_empty, .init = ddsrt_init, .fini = ddsrt_fini) {
/* Expected traces when creating participant with an empty security element. */
const char *log_expected[] = {
#ifndef DDSI_INCLUDE_SECURITY
"config: //CycloneDDS/Domain: DDSSecurity: unknown element*",
#else
"config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCertificate/#text: element missing in configuration*",
"config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCA/#text: element missing in configuration*",
"config: //CycloneDDS/Domain/DDSSecurity/Authentication/PrivateKey/#text: element missing in configuration*",
#endif
NULL
};
dds_entity_t participant;
/* Set up the trace sinks to detect the config parsing. */
dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG);
dds_set_log_sink(&logger, (void*)log_expected);
dds_set_trace_sink(&logger, (void*)log_expected);
/* Create participant with an empty security element. */
found = 0;
ddsrt_setenv(URI_VARIABLE, "<DDSSecurity/>");
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
ddsrt_setenv(URI_VARIABLE, "");
CU_ASSERT_FATAL(participant < 0);
/* All traces should have been provided. */
#ifndef DDSI_INCLUDE_SECURITY
CU_ASSERT_FATAL(found == 0x1);
#else
CU_ASSERT_FATAL(found == 0x7);
#endif
}
CU_Test(ddsc_config, security_missing, .init = ddsrt_init, .fini = ddsrt_fini) {
/* Expected traces when creating participant with the security elements. */
const char *log_expected[] = {
#ifndef DDSI_INCLUDE_SECURITY
"config: //CycloneDDS/Domain: DDSSecurity: unknown element*",
#else
"config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCertificate/#text: element missing in configuration*",
"config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCA/#text: element missing in configuration*",
"config: //CycloneDDS/Domain/DDSSecurity/Authentication/PrivateKey/#text: element missing in configuration*",
#endif
NULL
};
/* IdentityCertificate, IdentityCA and PrivateKey values or elements are missing. */
const char *sec_config =
"<Tracing><Verbosity>finest</></>"
"<DDSSecurity>"
"<Authentication>"
"<Library path=\"dds_security_auth\" initFunction=\"init_authentication\" finalizeFunction=\"finalize_authentication\" />"
"<IdentityCertificate></IdentityCertificate>"
"<PrivateKey></PrivateKey>"
"<Password>testtext_Password_testtext</Password>"
"</Authentication>"
"<Cryptographic>"
"<Library path=\"dds_security_crypto\" initFunction=\"init_crypto\" finalizeFunction=\"finalize_crypto\"/>"
"</Cryptographic>"
"<AccessControl>"
"<Library path=\"dds_security_ac\" initFunction=\"init_ac\" finalizeFunction=\"finalize_ac\"/>"
"<Governance>file:Governance.p7s</Governance>"
"<PermissionsCA>file:Permissions_CA.pem</PermissionsCA>"
"<Permissions>file:Permissions.p7s</Permissions>"
"</AccessControl>"
"</DDSSecurity>";
dds_entity_t participant;
/* Set up the trace sinks to detect the config parsing. */
dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG);
dds_set_log_sink(&logger, (void*)log_expected);
dds_set_trace_sink(&logger, (void*)log_expected);
/* Create participant with an empty security element. */
found = 0;
ddsrt_setenv(URI_VARIABLE, sec_config);
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
ddsrt_setenv(URI_VARIABLE, "");
CU_ASSERT_FATAL(participant < 0);
/* All traces should have been provided. */
#ifndef DDSI_INCLUDE_SECURITY
CU_ASSERT_FATAL(found == 0x1);
#else
CU_ASSERT_FATAL(found == 0x7);
#endif
}
CU_Test(ddsc_config, security_all, .init = ddsrt_init, .fini = ddsrt_fini) {
/* Expected traces when creating participant with the security elements. */
const char *log_expected[] = {
#ifndef DDSI_INCLUDE_SECURITY
"config: //CycloneDDS/Domain: DDSSecurity: unknown element*",
#else
"config: Domain/DDSSecurity/Authentication/Library/#text: dds_security_auth*",
"config: Domain/DDSSecurity/Authentication/Library[@path]: dds_security_auth*",
"config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_authentication*",
"config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_authentication*",
"config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: testtext_IdentityCertificate_testtext*",
"config: Domain/DDSSecurity/Authentication/IdentityCA/#text: testtext_IdentityCA_testtext*",
"config: Domain/DDSSecurity/Authentication/PrivateKey/#text: testtext_PrivateKey_testtext*",
"config: Domain/DDSSecurity/Authentication/Password/#text: testtext_Password_testtext*",
"config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: testtext_Dir_testtext*",
"config: Domain/DDSSecurity/AccessControl/Library/#text: dds_security_ac*",
"config: Domain/DDSSecurity/AccessControl/Library[@path]: dds_security_ac*",
"config: Domain/DDSSecurity/AccessControl/Library[@initFunction]: init_ac*",
"config: Domain/DDSSecurity/AccessControl/Library[@finalizeFunction]: finalize_ac*",
"config: Domain/DDSSecurity/AccessControl/PermissionsCA/#text: file:Permissions_CA.pem*",
"config: Domain/DDSSecurity/AccessControl/Governance/#text: file:Governance.p7s*",
"config: Domain/DDSSecurity/AccessControl/Permissions/#text: file:Permissions.p7s*",
"config: Domain/DDSSecurity/Cryptographic/Library/#text: dds_security_crypto*",
"config: Domain/DDSSecurity/Cryptographic/Library[@path]: dds_security_crypto*",
"config: Domain/DDSSecurity/Cryptographic/Library[@initFunction]: init_crypto*",
"config: Domain/DDSSecurity/Cryptographic/Library[@finalizeFunction]: finalize_crypto*",
/* The config should have been parsed into the participant QoS. */
"PARTICIPANT * QOS={*property_list={value={{dds.sec.auth.identity_ca,testtext_IdentityCA_testtext,0},{dds.sec.auth.private_key,testtext_PrivateKey_testtext,0},{dds.sec.auth.identity_certificate,testtext_IdentityCertificate_testtext,0},{dds.sec.access.permissions_ca,file:Permissions_CA.pem,0},{dds.sec.access.governance,file:Governance.p7s,0},{dds.sec.access.permissions,file:Permissions.p7s,0},{dds.sec.auth.password,testtext_Password_testtext,0},{dds.sec.auth.trusted_ca_dir,testtext_Dir_testtext,0}}binary_value={}}*}*",
#endif
NULL
};
const char *sec_config =
"<"DDS_PROJECT_NAME">"
"<Domain id=\"any\">"
"<Tracing><Verbosity>finest</></>"
"<DDSSecurity>"
"<Authentication>"
"<Library path=\"dds_security_auth\" initFunction=\"init_authentication\" finalizeFunction=\"finalize_authentication\" />"
"<IdentityCertificate>testtext_IdentityCertificate_testtext</IdentityCertificate>"
"<IdentityCA>testtext_IdentityCA_testtext</IdentityCA>"
"<PrivateKey>testtext_PrivateKey_testtext</PrivateKey>"
"<Password>testtext_Password_testtext</Password>"
"<TrustedCADirectory>testtext_Dir_testtext</TrustedCADirectory>"
"</Authentication>"
"<Cryptographic>"
"<Library path=\"dds_security_crypto\" initFunction=\"init_crypto\" finalizeFunction=\"finalize_crypto\"/>"
"</Cryptographic>"
"<AccessControl>"
"<Library path=\"dds_security_ac\" initFunction=\"init_ac\" finalizeFunction=\"finalize_ac\"/>"
"<Governance>file:Governance.p7s</Governance>"
"<PermissionsCA>file:Permissions_CA.pem</PermissionsCA>"
"<Permissions>file:Permissions.p7s</Permissions>"
"</AccessControl>"
"</DDSSecurity>"
"</Domain>"
"</"DDS_PROJECT_NAME">";
dds_entity_t participant;
/* Set up the trace sinks to detect the config parsing. */
dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG);
dds_set_log_sink(&logger, (void*)log_expected);
dds_set_trace_sink(&logger, (void*)log_expected);
/* Create participant with security elements. */
found = 0;
ddsrt_setenv(URI_VARIABLE, sec_config);
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
ddsrt_setenv(URI_VARIABLE, "");
dds_delete(participant);
/* All traces should have been provided. */
#ifndef DDSI_INCLUDE_SECURITY
CU_ASSERT_FATAL(found == 0x1);
#else
CU_ASSERT_FATAL(found == 0x1fffff);
#endif
}
CU_Test(ddsc_config, security, .init = ddsrt_init, .fini = ddsrt_fini) {
/* Expected traces when creating participant with the security elements. */
const char *log_expected[] = {
#ifndef DDSI_INCLUDE_SECURITY
"config: //CycloneDDS/Domain: DDSSecurity: unknown element*",
#else
"config: Domain/DDSSecurity/Authentication/Library/#text: dds_security_auth*",
"config: Domain/DDSSecurity/Authentication/Library[@path]: dds_security_auth*",
"config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_authentication*",
"config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_authentication*",
"config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: testtext_IdentityCertificate_testtext*",
"config: Domain/DDSSecurity/Authentication/IdentityCA/#text: testtext_IdentityCA_testtext*",
"config: Domain/DDSSecurity/Authentication/PrivateKey/#text: testtext_PrivateKey_testtext*",
"config: Domain/DDSSecurity/Authentication/Password/#text: {}*",
"config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: {}*",
"config: Domain/DDSSecurity/AccessControl/Library/#text: dds_security_ac*",
"config: Domain/DDSSecurity/AccessControl/Library[@path]: dds_security_ac*",
"config: Domain/DDSSecurity/AccessControl/Library[@initFunction]: init_ac*",
"config: Domain/DDSSecurity/AccessControl/Library[@finalizeFunction]: finalize_ac*",
"config: Domain/DDSSecurity/AccessControl/PermissionsCA/#text: file:Permissions_CA.pem*",
"config: Domain/DDSSecurity/AccessControl/Governance/#text: file:Governance.p7s*",
"config: Domain/DDSSecurity/AccessControl/Permissions/#text: file:Permissions.p7s*",
"config: Domain/DDSSecurity/Cryptographic/Library/#text: dds_security_crypto*",
"config: Domain/DDSSecurity/Cryptographic/Library[@path]: dds_security_crypto*",
"config: Domain/DDSSecurity/Cryptographic/Library[@initFunction]: init_crypto*",
"config: Domain/DDSSecurity/Cryptographic/Library[@finalizeFunction]: finalize_crypto*",
/* The config should have been parsed into the participant QoS. */
"PARTICIPANT * QOS={*property_list={value={{dds.sec.auth.identity_ca,testtext_IdentityCA_testtext,0},{dds.sec.auth.private_key,testtext_PrivateKey_testtext,0},{dds.sec.auth.identity_certificate,testtext_IdentityCertificate_testtext,0},{dds.sec.access.permissions_ca,file:Permissions_CA.pem,0},{dds.sec.access.governance,file:Governance.p7s,0},{dds.sec.access.permissions,file:Permissions.p7s,0}}binary_value={}}*}*",
#endif
NULL
};
const char *sec_config =
"<Tracing><Verbosity>finest</></>"
"<DDSSecurity>"
"<Authentication>"
"<Library path=\"dds_security_auth\" initFunction=\"init_authentication\" finalizeFunction=\"finalize_authentication\" />"
"<IdentityCertificate>testtext_IdentityCertificate_testtext</IdentityCertificate>"
"<IdentityCA>testtext_IdentityCA_testtext</IdentityCA>"
"<PrivateKey>testtext_PrivateKey_testtext</PrivateKey>"
"</Authentication>"
"<Cryptographic>"
"<Library path=\"dds_security_crypto\" initFunction=\"init_crypto\" finalizeFunction=\"finalize_crypto\"/>"
"</Cryptographic>"
"<AccessControl>"
"<Library path=\"dds_security_ac\" initFunction=\"init_ac\" finalizeFunction=\"finalize_ac\"/>"
"<Governance>file:Governance.p7s</Governance>"
"<PermissionsCA>file:Permissions_CA.pem</PermissionsCA>"
"<Permissions>file:Permissions.p7s</Permissions>"
"</AccessControl>"
"</DDSSecurity>";
dds_entity_t participant;
/* Set up the trace sinks to detect the config parsing. */
dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG);
dds_set_log_sink(&logger, (void*)log_expected);
dds_set_trace_sink(&logger, (void*)log_expected);
/* Create participant with security elements. */
found = 0;
ddsrt_setenv(URI_VARIABLE, sec_config);
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
ddsrt_setenv(URI_VARIABLE, "");
dds_delete(participant);
/* All traces should have been provided. */
#ifndef DDSI_INCLUDE_SECURITY
CU_ASSERT_FATAL(found == 0x1);
#else
CU_ASSERT_FATAL(found == 0x1fffff);
#endif
}
CU_Test(ddsc_config, security_deprecated, .init = ddsrt_init, .fini = ddsrt_fini) {
/* Expected traces when creating participant with the security elements. */
const char *log_expected[] = {
#ifndef DDSI_INCLUDE_SECURITY
"config: //CycloneDDS/Domain: DDSSecurity: unknown element*",
#else
"config: Domain/DDSSecurity/Authentication/Library/#text: dds_security_auth*",
"config: Domain/DDSSecurity/Authentication/Library[@path]: dds_security_auth*",
"config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_authentication*",
"config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_authentication*",
"config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: testtext_IdentityCertificate_testtext*",
"config: Domain/DDSSecurity/Authentication/IdentityCA/#text: testtext_IdentityCA_testtext*",
"config: Domain/DDSSecurity/Authentication/PrivateKey/#text: testtext_PrivateKey_testtext*",
"config: Domain/DDSSecurity/Authentication/Password/#text: testtext_Password_testtext*",
"config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: testtext_Dir_testtext*",
"config: Domain/DDSSecurity/AccessControl/Library/#text: dds_security_ac*",
"config: Domain/DDSSecurity/AccessControl/Library[@path]: dds_security_ac*",
"config: Domain/DDSSecurity/AccessControl/Library[@initFunction]: init_ac*",
"config: Domain/DDSSecurity/AccessControl/Library[@finalizeFunction]: finalize_ac*",
"config: Domain/DDSSecurity/AccessControl/PermissionsCA/#text: file:Permissions_CA.pem*",
"config: Domain/DDSSecurity/AccessControl/Governance/#text: file:Governance.p7s*",
"config: Domain/DDSSecurity/AccessControl/Permissions/#text: file:Permissions.p7s*",
"config: Domain/DDSSecurity/Cryptographic/Library/#text: dds_security_crypto*",
"config: Domain/DDSSecurity/Cryptographic/Library[@path]: dds_security_crypto*",
"config: Domain/DDSSecurity/Cryptographic/Library[@initFunction]: init_crypto*",
"config: Domain/DDSSecurity/Cryptographic/Library[@finalizeFunction]: finalize_crypto*",
/* The config should have been parsed into the participant QoS. */
"PARTICIPANT * QOS={*property_list={value={{dds.sec.auth.identity_ca,testtext_IdentityCA_testtext,0},{dds.sec.auth.private_key,testtext_PrivateKey_testtext,0},{dds.sec.auth.identity_certificate,testtext_IdentityCertificate_testtext,0},{dds.sec.access.permissions_ca,file:Permissions_CA.pem,0},{dds.sec.access.governance,file:Governance.p7s,0},{dds.sec.access.permissions,file:Permissions.p7s,0},{dds.sec.auth.password,testtext_Password_testtext,0},{dds.sec.auth.trusted_ca_dir,testtext_Dir_testtext,0}}binary_value={}}*}*",
#endif
NULL
};
const char *sec_config =
"<"DDS_PROJECT_NAME">"
"<Domain>"
"<Id>any</Id>"
"</Domain>"
"<DDSI2E>"
"<DDSSecurity>"
"<Authentication>"
"<Library path=\"dds_security_auth\" initFunction=\"init_authentication\" finalizeFunction=\"finalize_authentication\" />"
"<IdentityCertificate>testtext_IdentityCertificate_testtext</IdentityCertificate>"
"<IdentityCA>testtext_IdentityCA_testtext</IdentityCA>"
"<PrivateKey>testtext_PrivateKey_testtext</PrivateKey>"
"<Password>testtext_Password_testtext</Password>"
"<TrustedCADirectory>testtext_Dir_testtext</TrustedCADirectory>"
"</Authentication>"
"<Cryptographic>"
"<Library path=\"dds_security_crypto\" initFunction=\"init_crypto\" finalizeFunction=\"finalize_crypto\"/>"
"</Cryptographic>"
"<AccessControl>"
"<Library path=\"dds_security_ac\" initFunction=\"init_ac\" finalizeFunction=\"finalize_ac\"/>"
"<Governance>file:Governance.p7s</Governance>"
"<PermissionsCA>file:Permissions_CA.pem</PermissionsCA>"
"<Permissions>file:Permissions.p7s</Permissions>"
"</AccessControl>"
"</DDSSecurity>"
"<Tracing><Verbosity>finest</></>"
"</DDSI2E>"
"</"DDS_PROJECT_NAME">";
dds_entity_t participant;
/* Set up the trace sinks to detect the config parsing. */
dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG);
dds_set_log_sink(&logger, (void*)log_expected);
dds_set_trace_sink(&logger, (void*)log_expected);
/* Create participant with security elements. */
found = 0;
ddsrt_setenv(URI_VARIABLE, sec_config);
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
ddsrt_setenv(URI_VARIABLE, "");
dds_delete(participant);
/* All traces should have been provided. */
#ifndef DDSI_INCLUDE_SECURITY
CU_ASSERT_FATAL(found == 0x1);
#else
CU_ASSERT_FATAL(found == 0x1fffff);
#endif
}

View file

@ -210,6 +210,41 @@ enum many_sockets_mode {
MSM_MANY_UNICAST
};
#ifdef DDSI_INCLUDE_SECURITY
typedef struct plugin_library_properties_type{
char *library_path;
char *library_init;
char *library_finalize;
} plugin_library_properties_type;
typedef struct authentication_properties_type{
char *identity_certificate;
char *identity_ca;
char *private_key;
char *password;
char *trusted_ca_dir;
} authentication_properties_type;
typedef struct access_control_properties_type{
char *permissions;
char *permissions_ca;
char *governance;
} access_control_properties_type;
typedef struct omg_security_configuration_type {
authentication_properties_type authentication_properties;
access_control_properties_type access_control_properties;
plugin_library_properties_type authentication_plugin;
plugin_library_properties_type access_control_plugin;
plugin_library_properties_type cryptography_plugin;
} omg_security_configuration_type;
struct config_omg_security_listelem {
struct config_omg_security_listelem *next;
omg_security_configuration_type cfg;
};
#endif /* DDSI_INCLUDE_SECURITY */
#ifdef DDSI_INCLUDE_SSL
struct ssl_min_version {
int major;
@ -389,6 +424,10 @@ struct config
int use_multicast_if_mreqn;
struct prune_deleted_ppant prune_deleted_ppant;
#ifdef DDSI_INCLUDE_SECURITY
struct config_omg_security_listelem *omg_security_configuration;
#endif
};
struct cfgst;

View file

@ -35,7 +35,7 @@ unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr);
int WildcardOverlap(char * p1, char * p2);
#endif
int ddsi2_patmatch (const char *pat, const char *str);
DDS_EXPORT int ddsi2_patmatch (const char *pat, const char *str);
uint32_t crc32_calc (const void *buf, size_t length);

View file

@ -321,6 +321,10 @@ 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);
#ifdef DDSI_INCLUDE_SECURITY
struct omg_security_configuration_type;
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

@ -217,6 +217,9 @@ DI(if_partition_mapping);
#endif
DI(if_peer);
DI(if_thread_properties);
#ifdef DDSI_INCLUDE_SECURITY
DI(if_omg_security);
#endif
#undef DI
#define CO(name) ((int) offsetof (struct config, name))
@ -314,6 +317,149 @@ static const struct cfgelem security_cfgelems[] = {
};
#endif /* DDSI_INCLUDE_ENCRYPTION */
#ifdef DDSI_INCLUDE_SECURITY
/** Security Configuration */
static const struct cfgelem authentication_library_attributes[] = {
{ ATTR ("path"), 1, "dds_security_auth", RELOFF (config_omg_security_listelem, cfg.authentication_plugin.library_path), 0, uf_string, ff_free, pf_string,
BLURB("<p>This element points to the path of Authentication plugin library.</p>\n\
<p>It can be either absolute path excluding file extension ( /usr/lib/dds_security_auth ) or single file without extension ( dds_security_auth ).</p>\n\
<p>If single file is supplied, the library located by way of the current working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for Windows systems.</p>") },
{ ATTR ("initFunction"), 1, "init_authentication", RELOFF (config_omg_security_listelem, cfg.authentication_plugin.library_init), 0, uf_string, ff_free, pf_string,
BLURB("<p>This element names the initialization function of Authentication plugin. This function is called after loading the plugin library for instantiation purposes. Init function must return an object that implements DDS Security Authentication interface.</p>") },
{ ATTR ("finalizeFunction"), 1, "finalize_authentication", RELOFF (config_omg_security_listelem, cfg.authentication_plugin.library_finalize), 0, uf_string, ff_free, pf_string,
BLURB("<p>This element names the finalization function of Authentication plugin. This function is called to let the plugin release its resources.</p>") },
END_MARKER
};
static const struct cfgelem access_control_library_attributes[] = {
{ ATTR ("path"), 1, "dds_security_ac", RELOFF (config_omg_security_listelem, cfg.access_control_plugin.library_path), 0, uf_string, ff_free, pf_string,
BLURB("<p>This element points to the path of Access Control plugin library.</p>\n\
<p>It can be either absolute path excluding file extension ( /usr/lib/dds_security_ac ) or single file without extension ( dds_security_ac ).</p>\n\
<p>If single file is supplied, the library located by way of the current working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for Windows systems.</p>") },
{ ATTR ("initFunction"), 1, "init_access_control", RELOFF (config_omg_security_listelem, cfg.access_control_plugin.library_init), 0, uf_string, ff_free, pf_string,
BLURB("<p>This element names the initialization function of Access Control plugin. This function is called after loading the plugin library for instantiation purposes. Init function must return an object that implements DDS Security Access Control interface.</p>") },
{ ATTR ("finalizeFunction"), 1, "finalize_access_control", RELOFF (config_omg_security_listelem, cfg.access_control_plugin.library_finalize), 0, uf_string, ff_free, pf_string,
BLURB("<p>This element names the finalization function of Access Control plugin. This function is called to let the plugin release its resources.</p>") },
END_MARKER
};
static const struct cfgelem cryptography_library_attributes[] = {
{ ATTR ("path"), 1, "dds_security_crypto", RELOFF (config_omg_security_listelem, cfg.cryptography_plugin.library_path), 0, uf_string, ff_free, pf_string,
BLURB("<p>This element points to the path of Cryptographic plugin library.</p>\n\
<p>It can be either absolute path excluding file extension ( /usr/lib/dds_security_crypto ) or single file without extension ( dds_security_crypto ).</p>\n\
<p>If single file is supplied, the library located by way of the current working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for Windows systems.</p>") },
{ ATTR ("initFunction"), 1, "init_crypto", RELOFF (config_omg_security_listelem, cfg.cryptography_plugin.library_init), 0, uf_string, ff_free, pf_string,
BLURB("<p>This element names the initialization function of Cryptographic plugin. This function is called after loading the plugin library for instantiation purposes. Init function must return an object that implements DDS Security Cryptographic interface.</p>") },
{ ATTR ("finalizeFunction"), 1, "finalize_crypto", RELOFF (config_omg_security_listelem, cfg.cryptography_plugin.library_finalize), 0, uf_string, ff_free, pf_string,
BLURB("<p>This element names the finalization function of Cryptographic plugin. This function is called to let the plugin release its resources.</p>") },
END_MARKER
};
static const struct cfgelem authentication_config_elements[] = {
{ LEAF_W_ATTRS("Library", authentication_library_attributes), 1, "", RELOFF (config_omg_security_listelem, cfg.authentication_plugin), 0, 0, 0, pf_string,
BLURB("<p>This element specifies the library to be loaded as the DDS Security Access Control plugin.</p>") },
{ LEAF ("IdentityCertificate"), 1, NULL, RELOFF (config_omg_security_listelem, cfg.authentication_properties.identity_certificate), 0, uf_string, ff_free, pf_string,
BLURB("<p>Identity certificate that will be used for identifying all participants in the OSPL instance.<br>The content is URI to a X509 certificate signed by the IdentityCA in PEM format containing the signed public key.</p>\n\
<p>Supported URI schemes: file, data</p>\n\
<p>Examples:</p>\n\
<p><IdentityCertificate>file:participant1_identity_cert.pem</IdentityCertificate></p>\n\
<p><IdentityCertificate>data:,-----BEGIN CERTIFICATE-----<br>\n\
MIIDjjCCAnYCCQDCEu9...6rmT87dhTo=<br>\n\
-----END CERTIFICATE-----</IdentityCertificate></p>") },
{ LEAF ("IdentityCA"), 1, NULL, RELOFF (config_omg_security_listelem, cfg.authentication_properties.identity_ca), 0, uf_string, ff_free, pf_string,
BLURB("<p>URI to the X509 certificate [39] of the Identity CA that is the signer of Identity Certificate.</p>\n\
<p>Supported URI schemes: file, data</p>\n\
<p>The file and data schemas shall refer to a X.509 v3 certificate (see X.509 v3 ITU-T Recommendation X.509 (2005) [39]) in PEM format.</p>\n\
<p>Examples:</p>\n\
<p><IdentityCA>file:identity_ca.pem</IdentityCA></p>\n\
<p><IdentityCA>data:,-----BEGIN CERTIFICATE-----<br>\n\
MIIC3DCCAcQCCQCWE5x+Z...PhovK0mp2ohhRLYI0ZiyYQ==<br>\n\
-----END CERTIFICATE-----</IdentityCA></p>") },
{ LEAF ("PrivateKey"), 1, NULL, RELOFF (config_omg_security_listelem, cfg.authentication_properties.private_key), 0, uf_string, ff_free, pf_string,
BLURB("<p>URI to access the private Private Key for all of the participants in the OSPL federation.</p>\n\
<p>Supported URI schemes: file, data</p>\n\
<p>Examples:</p>\n\
<p><PrivateKey>file:identity_ca_private_key.pem</PrivateKey></p>\n\
<p><PrivateKey>data:,-----BEGIN RSA PRIVATE KEY-----<br>\n\
MIIEpAIBAAKCAQEA3HIh...AOBaaqSV37XBUJg==<br>\n\
-----END RSA PRIVATE KEY-----</PrivateKey></p>") },
{ LEAF ("Password"), 1, "", RELOFF (config_omg_security_listelem, cfg.authentication_properties.password), 0, uf_string, ff_free, pf_string,
BLURB("<p>A password used to decrypt the private_key.</p>\n\
The value of the password property shall be interpreted as the Base64 encoding of the AES-128 key that shall be used to decrypt the private_key using AES128-CBC.</p>\n\
If the password property is not present, then the value supplied in the private_key property must contain the unencrypted private key. </p>") },
{ LEAF ("TrustedCADirectory"), 1, "", RELOFF (config_omg_security_listelem, cfg.authentication_properties.trusted_ca_dir), 0, uf_string, ff_free, pf_string,
BLURB("<p>Trusted CA Directory which contains trusted CA certificates as separated files.</p>") },
END_MARKER
};
static const struct cfgelem access_control_config_elements[] = {
{ LEAF_W_ATTRS("Library", access_control_library_attributes), 1, "", RELOFF (config_omg_security_listelem, cfg.access_control_plugin), 0, 0, 0, pf_string,
BLURB("<p>This element specifies the library to be loaded as the DDS Security Access Control plugin.</p>") },
{ LEAF ("PermissionsCA"), 1, "", RELOFF (config_omg_security_listelem, cfg.access_control_properties.permissions_ca), 0, uf_string, ff_free, pf_string,
BLURB("<p>URI to a X509 certificate for the PermissionsCA in PEM format.</p>\n\
<p>Supported URI schemes: file, data</p>\n\
<p>The file and data schemas shall refer to a X.509 v3 certificate (see X.509 v3 ITU-T Recommendation X.509 (2005) [39]) in PEM format.</p><br>\n\
<p>Examples:</p><br>\n\
<p><PermissionsCA>file:permissions_ca.pem</PermissionsCA></p>\n\
<p><PermissionsCA>file:/home/myuser/permissions_ca.pem</PermissionsCA></p><br>\n\
<p><PermissionsCA>data:<strong>,</strong>-----BEGIN CERTIFICATE-----</p>\n\
<p>MIIC3DCCAcQCCQCWE5x+Z ... PhovK0mp2ohhRLYI0ZiyYQ==</p>\n\
<p>-----END CERTIFICATE-----</PermissionsCA></p>") },
{ LEAF ("Governance"), 1, "", RELOFF (config_omg_security_listelem, cfg.access_control_properties.governance), 0, uf_string, ff_free, pf_string,
BLURB("<p>URI to the shared Governance Document signed by the Permissions CA in S/MIME format</p>\n\
<p>URI schemes: file, data</p><br>\n\
<p>Examples file URIs:</p>\n\
<p><Governance>file:governance.smime</Governance></p>\n\
<p><Governance>file:/home/myuser/governance.smime</Governance></p><br>\n\
<p><Governance><![CDATA[data:,MIME-Version: 1.0</p>\n\
<p>Content-Type: multipart/signed; protocol=\"application/x-pkcs7-signature\"; micalg=\"sha-256\"; boundary=\"----F9A8A198D6F08E1285A292ADF14DD04F\"</p>\n\
<p>This is an S/MIME signed message </p>\n\
<p>------F9A8A198D6F08E1285A292ADF14DD04F</p>\n\
<p><?xml version=\"1.0\" encoding=\"UTF-8\"?></p>\n\
<p><dds xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"</p>\n\
<p>xsi:noNamespaceSchemaLocation=\"omg_shared_ca_governance.xsd\"></p>\n\
<p><domain_access_rules></p>\n\
<p> . . . </p>\n\
<p></domain_access_rules></p>\n\
<p></dds></p>\n\
<p>...</p>\n\
<p>------F9A8A198D6F08E1285A292ADF14DD04F</p>\n\
<p>Content-Type: application/x-pkcs7-signature; name=\"smime.p7s\"</p>\n\
<p>Content-Transfer-Encoding: base64</p>\n\
<p>Content-Disposition: attachment; filename=\"smime.p7s\"</p>\n\
<p>MIIDuAYJKoZIhv ...al5s=</p>\n\
<p>------F9A8A198D6F08E1285A292ADF14DD04F-]]</Governance></p>") },
{ LEAF ("Permissions"), 1, "", RELOFF (config_omg_security_listelem, cfg.access_control_properties.permissions), 0, uf_string, ff_free, pf_string,
BLURB("<p>URI to the DomainParticipant permissions document signed by the Permissions CA in S/MIME format</p>\n\
<p>The permissions document specifies the permissions to be applied to a domain.</p><br>\n\
<p>Example file URIs:</p>\n\
<p><Permissions>file:permissions_document.p7s</Permissions></p>\n\
<p><Permissions>file:/path_to/permissions_document.p7s</Permissions></p>\n\
<p>Example data URI:</p>\n\
<p><Permissions><![CDATA[data:,.........]]</Permissions></p>") },
END_MARKER
};
static const struct cfgelem cryptography_config_elements[] = {
{ LEAF_W_ATTRS("Library", cryptography_library_attributes), 1, "", RELOFF (config_omg_security_listelem, cfg.cryptography_plugin), 0, 0, 0, pf_string,
BLURB("<p>This element specifies the library to be loaded as the DDS Security Cryptographic plugin.</p>") },
END_MARKER
};
static const struct cfgelem security_omg_config_elements[] = {
{ GROUP ("Authentication", authentication_config_elements),
BLURB("<p>This element configures the Authentication plugin of the DDS Security specification.</p>") },
{ GROUP ("AccessControl", access_control_config_elements),
BLURB("<p>This element configures the Access Control plugin of the DDS Security specification.</p>") },
{ GROUP ("Cryptographic", cryptography_config_elements),
BLURB("<p>This element configures the Cryptographic plugin of the DDS Security specification.</p>") },
END_MARKER
};
#endif /* DDSI_INCLUDE_SECURITY */
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
static const struct cfgelem networkpartition_cfgattrs[] = {
{ ATTR("Name"), 1, NULL, RELOFF(config_networkpartition_listelem, name), 0, uf_string, ff_free, pf_string,
@ -814,6 +960,10 @@ static const struct cfgelem domain_cfgelems[] = {
{ GROUP("Security", security_cfgelems),
BLURB("<p>The Security element specifies DDSI2E security profiles that can be used to encrypt traffic mapped to DDSI2E network partitions.</p>") },
#endif
#ifdef DDSI_INCLUDE_SECURITY
{ MGROUP ("DDSSecurity", security_omg_config_elements, NULL), INT_MAX, NULL, ABSOFF(omg_security_configuration), if_omg_security, 0, 0, 0,
BLURB("<p>This element is used to configure DDSI2E with the DDS Security specification plugins and settings.</p>") },
#endif
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
{ GROUP("Partitioning", partitioning_cfgelems),
BLURB("<p>The Partitioning element specifies DDSI2E network partitions and how DCPS partition/topic combinations are mapped onto the network partitions.</p>") },
@ -866,6 +1016,9 @@ static const struct cfgelem root_cfgelems[] = {
{ MOVED("Internal|Unsupported", "CycloneDDS/Domain/Internal") },
{ MOVED("TCP", "CycloneDDS/Domain/TCP") },
{ MOVED("ThreadPool", "CycloneDDS/Domain/ThreadPool") },
#ifdef DDSI_INCLUDE_SECURITY
{ MOVED("DDSSecurity", "CycloneDDS/Domain/DDSSecurity") },
#endif
#ifdef DDSI_INCLUDE_SSL
{ MOVED("SSL", "CycloneDDS/Domain/SSL") },
#endif
@ -1310,6 +1463,17 @@ static int if_peer (struct cfgst *cfgst, void *parent, struct cfgelem const * co
return 0;
}
#ifdef DDSI_INCLUDE_SECURITY
static int if_omg_security (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
{
struct config_omg_security_listelem *new = if_common (cfgst, parent, cfgelem, sizeof (struct config_omg_security_listelem));
if (new == NULL)
return -1;
memset(&new->cfg, 0, sizeof(new->cfg));
return 0;
}
#endif
static void ff_free (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
{
void ** const elem = cfg_address (cfgst, parent, cfgelem);

View file

@ -516,6 +516,15 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *
nn_plist_copy (pp->plist, plist);
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)
{
/* For security, configuration can be provided through the configuration.
* However, the specification (and the plugins) expect it to be in the QoS. */
nn_xqos_mergein_security_config(&(pp->plist->qos), &(gv->config.omg_security_configuration->cfg));
}
#endif
if (gv->logconfig.c.mask & DDS_LC_DISCOVERY)
{
GVLOGDISC ("PARTICIPANT "PGUIDFMT" QOS={", PGUID (pp->e.guid));

View file

@ -2760,6 +2760,55 @@ dds_qos_t * nn_xqos_dup (const dds_qos_t *src)
return dst;
}
#ifdef DDSI_INCLUDE_SECURITY
static void fill_property(dds_property_t *prop, const char *name, const char *value)
{
prop->name = ddsrt_strdup(name);
prop->value = ddsrt_strdup(value);
prop->propagate = false;
}
void nn_xqos_mergein_security_config (dds_qos_t *xqos, const struct omg_security_configuration_type *cfg)
{
if (cfg)
{
/* Add DDS Security configuration to the QoS as a Property policy,
* used by the security plugins to get their proper settings. */
dds_property_t *properties;
uint32_t idx = 0;
/* No property should be present yet. */
assert(!(xqos->present & QP_PROPERTY_LIST));
/* Prepare properties. */
properties = ddsrt_malloc(8 /* max */ * sizeof (dds_property_t));
/* Fill properties. */
fill_property(&(properties[idx++]), "dds.sec.auth.identity_ca", cfg->authentication_properties.identity_ca);
fill_property(&(properties[idx++]), "dds.sec.auth.private_key", cfg->authentication_properties.private_key);
fill_property(&(properties[idx++]), "dds.sec.auth.identity_certificate", cfg->authentication_properties.identity_certificate);
fill_property(&(properties[idx++]), "dds.sec.access.permissions_ca", cfg->access_control_properties.permissions_ca);
fill_property(&(properties[idx++]), "dds.sec.access.governance", cfg->access_control_properties.governance);
fill_property(&(properties[idx++]), "dds.sec.access.permissions", cfg->access_control_properties.permissions);
if (cfg->authentication_properties.password && (strlen(cfg->authentication_properties.password) != 0))
{
fill_property(&(properties[idx++]), "dds.sec.auth.password", cfg->authentication_properties.password);
}
if (cfg->authentication_properties.trusted_ca_dir && (strlen(cfg->authentication_properties.trusted_ca_dir) != 0))
{
fill_property(&(properties[idx++]), "dds.sec.auth.trusted_ca_dir", cfg->authentication_properties.trusted_ca_dir);
}
/* Add properties. */
xqos->present |= QP_PROPERTY_LIST;
xqos->property.value.n = idx;
xqos->property.value.props = properties;
xqos->property.binary_value.n = 0;
xqos->property.binary_value.props = NULL;
}
}
#endif /* DDSI_INCLUDE_SECURITY */
static int partition_is_default (const dds_partition_qospolicy_t *a)
{
uint32_t i;