Add tests for discovery protection

Adding a test that checks the effects of using different configuration settings
for discovery protection. This test set uses the cryptography wrapper to count
the number of invocations of the encode and decode functions during a session
and checks the counts with the expected values.

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
This commit is contained in:
Dennis Potman 2020-04-24 19:43:55 +02:00 committed by eboasson
parent fd27604a26
commit 9f261423e3
9 changed files with 359 additions and 93 deletions

View file

@ -23,15 +23,20 @@
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/io.h"
#include "dds/ddsrt/string.h"
#include "dds/ddsi/q_entity.h"
#include "dds/ddsi/ddsi_entity_index.h"
#include "dds/ddsi/ddsi_security_omg.h"
#include "dds/ddsi/q_config.h"
#include "dds/ddsi/ddsi_domaingv.h"
#include "dds/ddsi/q_misc.h"
#include "dds/ddsi/ddsi_xqos.h"
#include "dds__entity.h"
#include "dds/security/dds_security_api.h"
#include "common/config_env.h"
#include "common/access_control_wrapper.h"
#include "common/cryptography_wrapper.h"
#include "common/security_config_test_utils.h"
#include "common/test_identity.h"
#include "common/test_utils.h"
@ -59,7 +64,7 @@ static const char *config =
" ${INCL_PERM:+<Permissions><![CDATA[}${TEST_PERMISSIONS}${INCL_PERM:+]]></Permissions>}"
" </AccessControl>"
" <Cryptographic>"
" <Library finalizeFunction=\"finalize_crypto\" initFunction=\"init_crypto\"/>"
" <Library initFunction=\"${CRYPTO_INIT:-init_test_cryptography_wrapped}\" finalizeFunction=\"${CRYPTO_INIT:-finalize_test_cryptography_wrapped}\" path=\"" WRAPPERLIB_PATH("dds_security_cryptography_wrapper") "\"/>"
" </Cryptographic>"
" </DDSSecurity>"
"</Domain>";
@ -114,6 +119,41 @@ static void access_control_fini(size_t n)
CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain[i]), DDS_RETCODE_OK);
}
static DDS_Security_DatawriterCryptoHandle get_builtin_writer_crypto_handle(dds_entity_t participant, unsigned entityid)
{
DDS_Security_DatawriterCryptoHandle crypto_handle;
struct dds_entity *pp_entity;
struct participant *pp;
struct writer *wr;
CU_ASSERT_EQUAL_FATAL(dds_entity_pin(participant, &pp_entity), 0);
thread_state_awake(lookup_thread_state(), &pp_entity->m_domain->gv);
pp = entidx_lookup_participant_guid(pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid);
wr = get_builtin_writer(pp, entityid);
CU_ASSERT_FATAL(wr != NULL);
assert(wr != NULL); /* for Clang's static analyzer */
crypto_handle = wr->sec_attr->crypto_handle;
thread_state_asleep(lookup_thread_state());
dds_entity_unpin(pp_entity);
return crypto_handle;
}
// static DDS_Security_DatawriterCryptoHandle get_writer_crypto_handle(dds_entity_t writer)
// {
// DDS_Security_DatawriterCryptoHandle crypto_handle;
// struct dds_entity *wr_entity;
// struct writer *wr;
// CU_ASSERT_EQUAL_FATAL(dds_entity_pin(writer, &wr_entity), 0);
// thread_state_awake(lookup_thread_state(), &wr_entity->m_domain->gv);
// wr = entidx_lookup_writer_guid(wr_entity->m_domain->gv.entity_index, &wr_entity->m_guid);
// CU_ASSERT_FATAL(wr != NULL);
// assert(wr != NULL); /* for Clang's static analyzer */
// crypto_handle = wr->sec_attr->crypto_handle;
// thread_state_asleep(lookup_thread_state());
// dds_entity_unpin(wr_entity);
// return crypto_handle;
// }
#define GOV_F PF_F COMMON_ETC_PATH("default_governance.p7s")
#define GOV_FNE PF_F COMMON_ETC_PATH("default_governance_non_existing.p7s")
#define GOV_DI PF_D COMMON_ETC_PATH("default_governance.p7s")
@ -512,11 +552,9 @@ CU_Theory(
get_permissions_grant ("id2", id2_subj, perm_inv_pp2 ? "99" : NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL) };
char * perm_config = get_permissions_config (grants, 2, true);
struct kvp governance_vars_pp1[] = { { "ENABLE_JOIN_AC", join_ac_pp1 ? "true" : "false", 1 }, { NULL, NULL, 0 } };
struct kvp governance_vars_pp2[] = { { "ENABLE_JOIN_AC", join_ac_pp2 ? "true" : "false", 1 }, { NULL, NULL, 0 } };
char * gov_config_pp1 = get_governance_config (governance_vars_pp1, true);
char * gov_config_pp2 = get_governance_config (governance_vars_pp2, true);
char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, "NONE", "NONE");
char * gov_config_pp1 = get_governance_config (false, join_ac_pp1, NULL, NULL, NULL, gov_topic_rule, true);
char * gov_config_pp2 = get_governance_config (false, join_ac_pp2, NULL, NULL, NULL, gov_topic_rule, true);
const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem");
access_control_init (
@ -536,6 +574,109 @@ CU_Theory(
ddsrt_free (gov_config_pp1);
ddsrt_free (gov_config_pp2);
ddsrt_free (gov_topic_rule);
ddsrt_free (perm_topic);
ddsrt_free (grants[0]);
ddsrt_free (grants[1]);
ddsrt_free (perm_config);
ddsrt_free (ca);
ddsrt_free (id1_subj);
ddsrt_free (id2_subj);
ddsrt_free (id1);
ddsrt_free (id2);
}
#define na false
#define E ENCRYPT
CU_TheoryDataPoints(ddssec_access_control, discovery_protection) = {
CU_DataPoints(const char *,
/* */"disabled",
/* | */"enabled, protection kind none",
/* | | */"disabled, protection kind encrypt",
/* | | | */"enabled, protection kind encrypt",
/* | | | | */"enabled, protection kind sign",
/* | | | | | */"enabled, protection kind encrypt-with-origin_auth",
/* | | | | | | */"enabled for node 1, disabled for node 2",
/* | | | | | | | */"node 1 and node 2 different protection kinds"),
CU_DataPoints(bool, false, true, false, true, true, true, true, true), /* enable_discovery_protection for pp 1 */
CU_DataPoints(bool, false, true, false, true, true, true, false, true), /* enable_discovery_protection for pp 2 */
CU_DataPoints(DDS_Security_ProtectionKind, PK_N, PK_N, PK_E, PK_E, PK_S, PK_EOA, PK_E, PK_E), /* discovery_protection_kind pp 1 */
CU_DataPoints(DDS_Security_ProtectionKind, PK_N, PK_N, PK_E, PK_E, PK_S, PK_EOA, PK_N, PK_S), /* discovery_protection_kind pp 2 */
CU_DataPoints(bool, false, false, false, false, false, false, true, true), /* expect rd-wr match fail */
CU_DataPoints(bool, false, false, true, true, true, true, true, true), /* expect SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER of pp 1 to have a crypto handle */
CU_DataPoints(bool, na, na, true, true, true, true, false, false), /* expect encode_datawriter_submessage for SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER of pp 1 */
};
#undef na
CU_Theory(
(const char * test_descr, bool enable_discovery_protection_pp1, bool enable_discovery_protection_pp2,
DDS_Security_ProtectionKind discovery_protection_kind_pp1, DDS_Security_ProtectionKind discovery_protection_kind_pp2,
bool exp_rd_wr_match_fail, bool exp_secure_pub_wr_handle, bool exp_secure_pub_wr_encode_decode),
ddssec_access_control, discovery_protection, .timeout=30)
{
print_test_msg ("running test discovery_protection: %s\n", test_descr);
char topic_name[100];
create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name));
/* create ca and id1/id2 certs that will not expire during this test */
char *ca, *id1, *id2, *id1_subj, *id2_subj;
ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600);
id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj);
id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj);
/* localtime will be converted to gmtime in get_permissions_grant */
dds_time_t now = dds_time ();
char * perm_topic = get_permissions_topic (topic_name);
char * grants[] = {
get_permissions_grant ("id1", id1_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL),
get_permissions_grant ("id2", id2_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL) };
char * perm_config = get_permissions_config (grants, 2, true);
char * gov_topic_rule1 = get_governance_topic_rule (topic_name, enable_discovery_protection_pp1, false, true, true, "ENCRYPT", "NONE");
char * gov_topic_rule2 = get_governance_topic_rule (topic_name, enable_discovery_protection_pp2, false, true, true, "ENCRYPT", "NONE");
char * gov_config1 = get_governance_config (false, true, pk_to_str (discovery_protection_kind_pp1), NULL, "ENCRYPT", gov_topic_rule1, true);
char * gov_config2 = get_governance_config (false, true, pk_to_str (discovery_protection_kind_pp2), NULL, "ENCRYPT", gov_topic_rule2, true);
const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem");
access_control_init (
2,
(const char *[]) { id1, id2 },
(const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY },
(const char *[]) { ca, ca },
(bool []) { false, false }, NULL, NULL,
(bool []) { true, true }, (const char *[]) { gov_config1, gov_config2 },
(bool []) { true, true }, (const char *[]) { perm_config, perm_config },
(bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca });
validate_handshake (DDS_DOMAINID, false, NULL, NULL, NULL);
dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd;
rd_wr_init (g_participant[0], &pub, &pub_tp, &wr, g_participant[1], &sub, &sub_tp, &rd, topic_name);
sync_writer_to_readers (g_participant[0], wr, exp_rd_wr_match_fail ? 0 : 1);
if (!exp_rd_wr_match_fail)
write_read_for (wr, g_participant[1], rd, DDS_MSECS (100), false, false);
DDS_Security_DatawriterCryptoHandle secure_pub_wr_handle = get_builtin_writer_crypto_handle (g_participant[0], NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER);
print_test_msg ("crypto handle for SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: %ld\n", secure_pub_wr_handle);
CU_ASSERT_EQUAL_FATAL (exp_secure_pub_wr_handle, secure_pub_wr_handle != 0);
struct dds_security_cryptography_impl * crypto_context_pub = get_crypto_context (g_participant[0]);
CU_ASSERT_FATAL (crypto_context_pub != NULL);
struct crypto_encode_decode_data *log = get_encode_decode_log (crypto_context_pub, ENCODE_DATAWRITER_SUBMESSAGE, secure_pub_wr_handle);
CU_ASSERT_EQUAL_FATAL (exp_secure_pub_wr_handle && exp_secure_pub_wr_encode_decode, log != NULL);
if (log != NULL)
{
print_test_msg ("encode_datawriter_submessage count for SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: %u\n", log->count);
CU_ASSERT_FATAL (log->count > 0);
ddsrt_free (log);
}
access_control_fini (2);
ddsrt_free (gov_config1);
ddsrt_free (gov_config2);
ddsrt_free (gov_topic_rule1);
ddsrt_free (gov_topic_rule2);
ddsrt_free (perm_topic);
ddsrt_free (grants[0]);
ddsrt_free (grants[1]);

View file

@ -101,15 +101,8 @@ static void authentication_init(
if (perm_config == NULL)
perm_config = DEF_PERM_CONF;
struct kvp governance_vars[] = {
{ "DISCOVERY_PROTECTION_KIND", "NONE", 1 },
{ "LIVELINESS_PROTECTION_KIND", "NONE", 1 },
{ "RTPS_PROTECTION_KIND", "NONE", 1 },
{ "METADATA_PROTECTION_KIND", "NONE", 1 },
{ "DATA_PROTECTION_KIND", "NONE", 1 },
{ NULL, NULL, 0 }
};
char * gov_config_signed = get_governance_config (governance_vars, true);
char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, "NONE", "NONE");
char * gov_config_signed = get_governance_config (false, false, NULL, NULL, NULL, gov_topic_rule, true);
struct kvp config_vars1[] = {
{ "TEST_IDENTITY_CERTIFICATE", id1_cert, 1 },
@ -143,6 +136,7 @@ static void authentication_init(
CU_ASSERT_EQUAL_FATAL (exp_pp2_fail, g_participant2 <= 0);
ddsrt_free (gov_config_signed);
ddsrt_free (gov_topic_rule);
ddsrt_free (conf1);
ddsrt_free (conf2);
}

View file

@ -74,6 +74,8 @@ struct dds_security_cryptography_impl {
const char * encrypted_secret;
ddsrt_mutex_t token_data_lock;
struct ddsrt_circlist token_data_list;
ddsrt_mutex_t encode_decode_log_lock;
struct ddsrt_circlist encode_decode_log;
};
static DDS_Security_ParticipantCryptoHandle g_local_participant_handle = 0;
@ -211,6 +213,12 @@ struct ddsrt_circlist * get_crypto_tokens (struct dds_security_cryptography_impl
ddsrt_circlist_init (tokens);
ddsrt_mutex_lock (&impl->token_data_lock);
if (ddsrt_circlist_isempty (&impl->encode_decode_log))
{
ddsrt_mutex_unlock (&impl->token_data_lock);
return tokens;
}
struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->token_data_list), *elem = elem0;
while (elem != NULL)
{
@ -231,6 +239,11 @@ struct crypto_token_data * find_crypto_token (struct dds_security_cryptography_i
{
assert (data_len <= CRYPTO_TOKEN_SIZE);
ddsrt_mutex_lock (&impl->token_data_lock);
if (ddsrt_circlist_isempty (&impl->encode_decode_log))
{
ddsrt_mutex_unlock (&impl->token_data_lock);
return NULL;
}
struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->token_data_list), *elem = elem0;
while (elem != NULL)
{
@ -256,6 +269,60 @@ struct crypto_token_data * find_crypto_token (struct dds_security_cryptography_i
return NULL;
}
static void log_encode_decode (struct dds_security_cryptography_impl * impl, enum crypto_encode_decode_fn function, DDS_Security_long_long handle)
{
ddsrt_mutex_lock (&impl->encode_decode_log_lock);
if (!ddsrt_circlist_isempty (&impl->encode_decode_log))
{
struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->encode_decode_log), *elem = elem0;
while (elem != NULL)
{
struct crypto_encode_decode_data *data = DDSRT_FROM_CIRCLIST (struct crypto_encode_decode_data, e, elem);
if (data->function == function && data->handle == handle)
{
data->count++;
ddsrt_mutex_unlock (&impl->encode_decode_log_lock);
return;
}
elem = elem->next;
if (elem == elem0)
break;
}
}
/* add new entry */
struct crypto_encode_decode_data *new_data = ddsrt_malloc (sizeof (*new_data));
new_data->function = function;
new_data->handle = handle;
new_data->count = 1;
ddsrt_circlist_append(&impl->encode_decode_log, &new_data->e);
ddsrt_mutex_unlock (&impl->encode_decode_log_lock);
}
struct crypto_encode_decode_data * get_encode_decode_log (struct dds_security_cryptography_impl * impl, enum crypto_encode_decode_fn function, DDS_Security_long_long handle)
{
ddsrt_mutex_lock (&impl->encode_decode_log_lock);
if (!ddsrt_circlist_isempty (&impl->encode_decode_log))
{
struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->encode_decode_log), *elem = elem0;
while (elem != NULL)
{
struct crypto_encode_decode_data *data = DDSRT_FROM_CIRCLIST (struct crypto_encode_decode_data, e, elem);
if (data->function == function && data->handle == handle)
{
struct crypto_encode_decode_data *result = ddsrt_malloc (sizeof (*result));
memcpy (result, data, sizeof (*result));
ddsrt_mutex_unlock (&impl->encode_decode_log_lock);
return result;
}
elem = elem->next;
if (elem == elem0)
break;
}
}
ddsrt_mutex_unlock (&impl->encode_decode_log_lock);
return NULL;
}
static unsigned char * find_buffer_match(const unsigned char *input, size_t input_len, const unsigned char *match, size_t match_len)
{
if (match_len <= input_len && match_len > 0 && input_len > 0)
@ -705,6 +772,8 @@ static DDS_Security_boolean encode_datawriter_submessage(
switch (impl->parent->mode)
{
case PLUGIN_MODE_WRAPPED:
log_encode_decode (impl->parent, ENCODE_DATAWRITER_SUBMESSAGE, sending_datawriter_crypto);
/* fall-through */
case PLUGIN_MODE_TOKEN_LOG:
if (!impl->instance->encode_datawriter_submessage (impl->instance, encoded_rtps_submessage,
plain_rtps_submessage, check_handle (sending_datawriter_crypto), receiving_datareader_crypto_list, receiving_datareader_crypto_list_index, ex))
@ -753,6 +822,8 @@ static DDS_Security_boolean encode_datareader_submessage(
switch (impl->parent->mode)
{
case PLUGIN_MODE_WRAPPED:
log_encode_decode (impl->parent, ENCODE_DATAREADER_SUBMESSAGE, sending_datareader_crypto);
/* fall-through */
case PLUGIN_MODE_TOKEN_LOG:
if (!impl->instance->encode_datareader_submessage (impl->instance, encoded_rtps_submessage,
plain_rtps_submessage, check_handle (sending_datareader_crypto), receiving_datawriter_crypto_list, ex))
@ -850,6 +921,8 @@ static DDS_Security_boolean decode_datawriter_submessage(
switch (impl->parent->mode)
{
case PLUGIN_MODE_WRAPPED:
log_encode_decode (impl->parent, DECODE_DATAWRITER_SUBMESSAGE, receiving_datareader_crypto);
/* fall-through */
case PLUGIN_MODE_TOKEN_LOG:
return impl->instance->decode_datawriter_submessage (impl->instance, plain_rtps_submessage,
encoded_rtps_submessage, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex);
@ -870,6 +943,8 @@ static DDS_Security_boolean decode_datareader_submessage(
switch (impl->parent->mode)
{
case PLUGIN_MODE_WRAPPED:
log_encode_decode (impl->parent, DECODE_DATAREADER_SUBMESSAGE, receiving_datawriter_crypto);
/* fall-through */
case PLUGIN_MODE_TOKEN_LOG:
return impl->instance->decode_datareader_submessage (impl->instance, plain_rtps_submessage,
encoded_rtps_submessage, check_handle (receiving_datawriter_crypto), check_handle (sending_datareader_crypto), ex);
@ -1006,6 +1081,8 @@ int init_test_cryptography_wrapped(const char *argument, void **context, struct
if (!impl)
return DDS_SECURITY_FAILED;
impl->mode = PLUGIN_MODE_WRAPPED;
ddsrt_mutex_init (&impl->encode_decode_log_lock);
ddsrt_circlist_init (&impl->encode_decode_log);
*context = impl;
return DDS_SECURITY_SUCCESS;
}
@ -1014,6 +1091,15 @@ int finalize_test_cryptography_wrapped(void *context)
{
struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context;
assert(impl->mode == PLUGIN_MODE_WRAPPED);
ddsrt_mutex_lock (&impl->encode_decode_log_lock);
while (!ddsrt_circlist_isempty (&impl->encode_decode_log))
{
struct ddsrt_circlist_elem *list_elem = ddsrt_circlist_oldest (&impl->encode_decode_log);
ddsrt_circlist_remove (&impl->encode_decode_log, list_elem);
ddsrt_free (list_elem);
}
ddsrt_mutex_unlock (&impl->encode_decode_log_lock);
ddsrt_mutex_destroy (&impl->encode_decode_log_lock);
return finalize_test_cryptography_common(impl, true);
}
@ -1043,12 +1129,12 @@ int32_t finalize_test_cryptography_store_tokens(void *context)
while (!ddsrt_circlist_isempty (&impl->token_data_list))
{
struct ddsrt_circlist_elem *list_elem = ddsrt_circlist_oldest (&impl->token_data_list);
struct crypto_token_data *token_data = DDSRT_FROM_CIRCLIST (struct crypto_token_data, e, list_elem);
ddsrt_circlist_remove (&impl->token_data_list, list_elem);
ddsrt_free (token_data);
ddsrt_free (list_elem);
}
ddsrt_mutex_unlock (&impl->token_data_lock);
ddsrt_mutex_destroy (&impl->token_data_lock);
/* don't detroy g_print_token_lock as this will result in multiple
calls to mutex_destroy for this lock in case of multiple domains */

View file

@ -43,6 +43,20 @@ struct crypto_token_data {
size_t data_len[CRYPTO_TOKEN_MAXLEN];
};
enum crypto_encode_decode_fn {
ENCODE_DATAWRITER_SUBMESSAGE,
ENCODE_DATAREADER_SUBMESSAGE,
DECODE_DATAWRITER_SUBMESSAGE,
DECODE_DATAREADER_SUBMESSAGE
};
struct crypto_encode_decode_data {
struct ddsrt_circlist_elem e;
enum crypto_encode_decode_fn function;
DDS_Security_long_long handle;
uint32_t count;
};
SECURITY_EXPORT void set_protection_kinds(
struct dds_security_cryptography_impl * impl,
DDS_Security_ProtectionKind rtps_protection_kind,
@ -61,6 +75,7 @@ SECURITY_EXPORT void set_entity_data_secret(struct dds_security_cryptography_imp
SECURITY_EXPORT const char *get_crypto_token_type_str (enum crypto_tokens_type type);
SECURITY_EXPORT struct ddsrt_circlist * get_crypto_tokens (struct dds_security_cryptography_impl * impl);
SECURITY_EXPORT struct crypto_token_data * find_crypto_token (struct dds_security_cryptography_impl * impl, enum crypto_tokens_type type, unsigned char * data, size_t data_len);
SECURITY_EXPORT struct crypto_encode_decode_data * get_encode_decode_log (struct dds_security_cryptography_impl * impl, enum crypto_encode_decode_fn function, DDS_Security_long_long handle);
/* Init in all-ok mode: all functions return success without calling the actual plugin */
SECURITY_EXPORT int init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv);

View file

@ -29,6 +29,17 @@
#include "common/config_env.h"
#include "security_config_test_utils.h"
static const char *topic_rule =
" <topic_rule>"
" <topic_expression>${TOPIC_EXPRESSION}</topic_expression>"
" <enable_discovery_protection>${ENABLE_DISC_PROTECTION}</enable_discovery_protection>"
" <enable_liveliness_protection>${ENABLE_LIVELINESS_PROTECTION}</enable_liveliness_protection>"
" <enable_read_access_control>${ENABLE_READ_AC}</enable_read_access_control>"
" <enable_write_access_control>${ENABLE_WRITE_AC}</enable_write_access_control>"
" <metadata_protection_kind>${METADATA_PROTECTION_KIND}</metadata_protection_kind>"
" <data_protection_kind>${DATA_PROTECTION_KIND}</data_protection_kind>"
" </topic_rule>";
static const char *governance_xml =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<dds xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"https://www.omg.org/spec/DDS-SECURITY/20170901/omg_shared_ca_governance.xsd\">"
@ -46,15 +57,7 @@ static const char *governance_xml =
" <liveliness_protection_kind>${LIVELINESS_PROTECTION_KIND:-NONE}</liveliness_protection_kind>"
" <rtps_protection_kind>${RTPS_PROTECTION_KIND:-NONE}</rtps_protection_kind>"
" <topic_access_rules>"
" <topic_rule>"
" <topic_expression>*</topic_expression>"
" <enable_discovery_protection>${ENABLE_DISC_PROTECTION:-false}</enable_discovery_protection>"
" <enable_liveliness_protection>${ENABLE_LIVELINESS_PROTECTION:-false}</enable_liveliness_protection>"
" <enable_read_access_control>${ENABLE_READ_AC:-true}</enable_read_access_control>"
" <enable_write_access_control>${ENABLE_WRITE_AC:-true}</enable_write_access_control>"
" <metadata_protection_kind>${METADATA_PROTECTION_KIND:-NONE}</metadata_protection_kind>"
" <data_protection_kind>${DATA_PROTECTION_KIND:-NONE}</data_protection_kind>"
" </topic_rule>"
" ${TOPIC_RULES}"
" </topic_access_rules>"
" </domain_rule>"
" </domain_access_rules>"
@ -207,11 +210,48 @@ static char * prefix_data (char * config_signed, bool add_prefix)
return config_signed;
}
char * get_governance_config(struct kvp *config_vars, bool add_prefix)
static void print_config_vars(struct kvp *vars)
{
char * config = ddsrt_expand_vars (governance_xml, &expand_lookup_vars, config_vars);
for (uint32_t i = 0; vars[i].key != NULL; i++)
printf("%s=%s; ", vars[i].key, vars[i].value);
}
char * get_governance_topic_rule(const char * topic_expr, bool discovery_protection, bool liveliness_protection,
bool read_ac, bool write_ac, const char * metadata_protection_kind, const char * data_protection_kind)
{
struct kvp vars[] = {
{ "TOPIC_EXPRESSION", topic_expr != NULL ? topic_expr : "*", 1 },
{ "ENABLE_DISC_PROTECTION", discovery_protection ? "true" : "false", 1 },
{ "ENABLE_LIVELINESS_PROTECTION", liveliness_protection ? "true" : "false", 1 },
{ "ENABLE_READ_AC", read_ac ? "true" : "false", 1 },
{ "ENABLE_WRITE_AC", write_ac ? "true" : "false", 1 },
{ "METADATA_PROTECTION_KIND", metadata_protection_kind != NULL ? metadata_protection_kind : "NONE", 1 },
{ "DATA_PROTECTION_KIND", data_protection_kind != NULL ? data_protection_kind : "NONE", 1 },
{ NULL, NULL, 0 }
};
return ddsrt_expand_vars (topic_rule, &expand_lookup_vars, vars);
}
char * get_governance_config(bool allow_unauth_pp, bool enable_join_ac, const char * discovery_protection_kind, const char * liveliness_protection_kind,
const char * rtps_protection_kind, const char * topic_rules, bool add_prefix)
{
struct kvp vars[] = {
{ "ALLOW_UNAUTH_PP", allow_unauth_pp ? "true" : "false", 1 },
{ "ENABLE_JOIN_AC", enable_join_ac ? "true" : "false", 1 },
{ "DISCOVERY_PROTECTION_KIND", discovery_protection_kind != NULL ? discovery_protection_kind : "NONE", 1 },
{ "LIVELINESS_PROTECTION_KIND", liveliness_protection_kind != NULL ? liveliness_protection_kind : "NONE", 1 },
{ "RTPS_PROTECTION_KIND", rtps_protection_kind != NULL ? rtps_protection_kind : "NONE", 1 },
{ "TOPIC_RULES", topic_rules != NULL ? topic_rules : get_governance_topic_rule (NULL, false, false, false, false, NULL, NULL), 1 },
{ NULL, NULL, 0 }
};
char * config = ddsrt_expand_vars (governance_xml, &expand_lookup_vars, vars);
char * config_signed = get_signed_data (config);
ddsrt_free (config);
printf("Governance configuration: ");
print_config_vars(vars);
printf("\n");
return prefix_data (config_signed, add_prefix);
}

View file

@ -25,7 +25,11 @@ const char * expand_lookup_vars (const char *name, void * data);
const char * expand_lookup_vars_env (const char *name, void * data);
int32_t expand_lookup_unmatched (const struct kvp * lookup_table);
char * get_governance_config (struct kvp *config_vars, bool add_prefix);
char * get_governance_topic_rule(const char * topic_expr, bool discovery_protection, bool liveliness_protection,
bool read_ac, bool write_ac, const char * metadata_protection_kind, const char * data_protection_kind);
char * get_governance_config(bool allow_unauth_pp, bool enable_join_ac, const char * discovery_protection_kind, const char * liveliness_protection_kind,
const char * rtps_protection_kind, const char * topic_rules, bool add_prefix);
char * get_permissions_topic(const char * name);
char * get_permissions_grant(const char * name, const char * subject, const char * domain_id,
dds_time_t not_before, dds_time_t not_after, const char * pub_topics, const char * sub_topics, const char * default_policy);

View file

@ -38,6 +38,12 @@ int numRemote = 0;
struct Handshake handshakeList[MAX_HANDSHAKES];
int numHandshake = 0;
const char * g_pk_none = "NONE";
const char * g_pk_sign = "SIGN";
const char * g_pk_encrypt = "ENCRYPT";
const char * g_pk_sign_oa = "SIGN_WITH_ORIGIN_AUTHENTICATION";
const char * g_pk_encrypt_oa = "ENCRYPT_WITH_ORIGIN_AUTHENTICATION";
static char * get_validation_result_str (DDS_Security_ValidationResult_t result)
{
switch (result)
@ -471,3 +477,29 @@ struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t particip
dds_entity_unlock (pp_entity);
return context;
}
const char * pk_to_str(DDS_Security_ProtectionKind pk)
{
switch (pk)
{
case DDS_SECURITY_PROTECTION_KIND_NONE: return g_pk_none;
case DDS_SECURITY_PROTECTION_KIND_SIGN: return g_pk_sign;
case DDS_SECURITY_PROTECTION_KIND_ENCRYPT: return g_pk_encrypt;
case DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION: return g_pk_sign_oa;
case DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION: return g_pk_encrypt_oa;
}
assert (false);
return NULL;
}
const char * bpk_to_str(DDS_Security_BasicProtectionKind bpk)
{
switch (bpk)
{
case DDS_SECURITY_BASICPROTECTION_KIND_NONE: return g_pk_none;
case DDS_SECURITY_BASICPROTECTION_KIND_SIGN: return g_pk_sign;
case DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT: return g_pk_encrypt;
}
assert (false);
return NULL;
}

View file

@ -17,6 +17,15 @@
#include "dds/security/dds_security_api.h"
#define PK_N DDS_SECURITY_PROTECTION_KIND_NONE
#define PK_S DDS_SECURITY_PROTECTION_KIND_SIGN
#define PK_SOA DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION
#define PK_E DDS_SECURITY_PROTECTION_KIND_ENCRYPT
#define PK_EOA DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION
#define BPK_N DDS_SECURITY_BASICPROTECTION_KIND_NONE
#define BPK_S DDS_SECURITY_BASICPROTECTION_KIND_SIGN
#define BPK_E DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT
#define MAX_LOCAL_IDENTITIES 8
#define MAX_REMOTE_IDENTITIES 8
#define MAX_HANDSHAKES 32
@ -70,5 +79,7 @@ void rd_wr_init_fail(
bool exp_subtp_fail, bool exp_rd_fail);
void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_duration_t dur, bool exp_write_fail, bool exp_read_fail);
struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t participant);
const char * pk_to_str(DDS_Security_ProtectionKind pk);
const char * bpk_to_str(DDS_Security_BasicProtectionKind bpk);
#endif /* SECURITY_CORE_TEST_UTILS_H_ */

View file

@ -37,15 +37,6 @@
#include "SecurityCoreTests.h"
#define PK_N DDS_SECURITY_PROTECTION_KIND_NONE
#define PK_S DDS_SECURITY_PROTECTION_KIND_SIGN
#define PK_SOA DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION
#define PK_E DDS_SECURITY_PROTECTION_KIND_ENCRYPT
#define PK_EOA DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION
#define BPK_N DDS_SECURITY_BASICPROTECTION_KIND_NONE
#define BPK_S DDS_SECURITY_BASICPROTECTION_KIND_SIGN
#define BPK_E DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT
static const char *config =
"${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}"
"<Domain id=\"any\">"
@ -80,16 +71,6 @@ static const char *config =
#define MAX_DOMAINS 10
#define MAX_PARTICIPANTS 10
const char * g_pk_none = "NONE";
const char * g_pk_sign = "SIGN";
const char * g_pk_encrypt = "ENCRYPT";
const char * g_pk_sign_oa = "SIGN_WITH_ORIGIN_AUTHENTICATION";
const char * g_pk_encrypt_oa = "ENCRYPT_WITH_ORIGIN_AUTHENTICATION";
const char * g_pp_secret = "ppsecret";
const char * g_groupdata_secret = "groupsecret";
const char * g_ep_secret = "epsecret";
uint32_t g_topic_nr = 0;
static dds_entity_t g_pub_domains[MAX_DOMAINS];
@ -116,37 +97,9 @@ typedef void (*set_crypto_params_fn)(struct dds_security_cryptography_impl *, co
typedef dds_entity_t (*pubsub_create_fn)(dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener);
typedef dds_entity_t (*ep_create_fn)(dds_entity_t, dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener);
static const char * pk_to_str(DDS_Security_ProtectionKind pk)
{
switch (pk)
{
case DDS_SECURITY_PROTECTION_KIND_NONE: return g_pk_none;
case DDS_SECURITY_PROTECTION_KIND_SIGN: return g_pk_sign;
case DDS_SECURITY_PROTECTION_KIND_ENCRYPT: return g_pk_encrypt;
case DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION: return g_pk_sign_oa;
case DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION: return g_pk_encrypt_oa;
}
assert (false);
return NULL;
}
static const char * bpk_to_str(DDS_Security_BasicProtectionKind bpk)
{
switch (bpk)
{
case DDS_SECURITY_BASICPROTECTION_KIND_NONE: return g_pk_none;
case DDS_SECURITY_BASICPROTECTION_KIND_SIGN: return g_pk_sign;
case DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT: return g_pk_encrypt;
}
assert (false);
return NULL;
}
static void print_config_vars(struct kvp *vars)
{
for (uint32_t i = 0; vars[i].key != NULL; i++)
printf("%s=%s; ", vars[i].key, vars[i].value);
}
const char * g_pp_secret = "ppsecret";
const char * g_groupdata_secret = "groupsecret";
const char * g_ep_secret = "epsecret";
static dds_qos_t *get_qos()
{
@ -201,20 +154,9 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s
assert (n_pub_domains < MAX_DOMAINS);
assert (n_pub_participants < MAX_PARTICIPANTS);
struct kvp governance_vars[] = {
{ "DISCOVERY_PROTECTION_KIND", pk_to_str (domain_config->discovery_pk), 1 },
{ "LIVELINESS_PROTECTION_KIND", pk_to_str (domain_config->liveliness_pk), 1 },
{ "RTPS_PROTECTION_KIND", pk_to_str (domain_config->rtps_pk), 1 },
{ "METADATA_PROTECTION_KIND", pk_to_str (domain_config->metadata_pk), 1 },
{ "DATA_PROTECTION_KIND", bpk_to_str (domain_config->payload_pk), 1 },
{ NULL, NULL, 0 }
};
printf("Governance configuration: ");
print_config_vars(governance_vars);
printf("\n");
char * gov_config_signed = get_governance_config (governance_vars, false);
char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, pk_to_str (domain_config->metadata_pk), bpk_to_str (domain_config->payload_pk));
char * gov_config_signed = get_governance_config (false, false, pk_to_str (domain_config->discovery_pk), pk_to_str (domain_config->liveliness_pk),
pk_to_str (domain_config->rtps_pk), gov_topic_rule, false);
struct kvp config_vars[] = {
{ "GOVERNANCE_DATA", gov_config_signed, 1 },
@ -232,6 +174,7 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s
dds_free (conf_sub);
dds_free (gov_config_signed);
dds_free (gov_topic_rule);
}
static void test_fini(size_t n_sub_domain, size_t n_pub_domain)