From 9f261423e3ef0727a960001cc4c23f918f5474ea Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Fri, 24 Apr 2020 19:43:55 +0200 Subject: [PATCH] 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 --- src/security/core/tests/access_control.c | 153 +++++++++++++++++- src/security/core/tests/authentication.c | 12 +- .../core/tests/common/cryptography_wrapper.c | 90 ++++++++++- .../core/tests/common/cryptography_wrapper.h | 15 ++ .../tests/common/security_config_test_utils.c | 62 +++++-- .../tests/common/security_config_test_utils.h | 6 +- src/security/core/tests/common/test_utils.c | 32 ++++ src/security/core/tests/common/test_utils.h | 11 ++ .../core/tests/secure_communication.c | 71 +------- 9 files changed, 359 insertions(+), 93 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 3b04fc6..23c32f3 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -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:+}" " " " " - " " + " " " " " " ""; @@ -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]); diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index dbd80be..0af4138 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -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); } diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c index 1856c09..990e2c8 100644 --- a/src/security/core/tests/common/cryptography_wrapper.c +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -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 */ diff --git a/src/security/core/tests/common/cryptography_wrapper.h b/src/security/core/tests/common/cryptography_wrapper.h index b9384c9..d802247 100644 --- a/src/security/core/tests/common/cryptography_wrapper.h +++ b/src/security/core/tests/common/cryptography_wrapper.h @@ -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); diff --git a/src/security/core/tests/common/security_config_test_utils.c b/src/security/core/tests/common/security_config_test_utils.c index d66ff2d..74f3e5e 100644 --- a/src/security/core/tests/common/security_config_test_utils.c +++ b/src/security/core/tests/common/security_config_test_utils.c @@ -29,6 +29,17 @@ #include "common/config_env.h" #include "security_config_test_utils.h" +static const char *topic_rule = + " " + " ${TOPIC_EXPRESSION}" + " ${ENABLE_DISC_PROTECTION}" + " ${ENABLE_LIVELINESS_PROTECTION}" + " ${ENABLE_READ_AC}" + " ${ENABLE_WRITE_AC}" + " ${METADATA_PROTECTION_KIND}" + " ${DATA_PROTECTION_KIND}" + " "; + static const char *governance_xml = "" "" @@ -46,15 +57,7 @@ static const char *governance_xml = " ${LIVELINESS_PROTECTION_KIND:-NONE}" " ${RTPS_PROTECTION_KIND:-NONE}" " " - " " - " *" - " ${ENABLE_DISC_PROTECTION:-false}" - " ${ENABLE_LIVELINESS_PROTECTION:-false}" - " ${ENABLE_READ_AC:-true}" - " ${ENABLE_WRITE_AC:-true}" - " ${METADATA_PROTECTION_KIND:-NONE}" - " ${DATA_PROTECTION_KIND:-NONE}" - " " + " ${TOPIC_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); } diff --git a/src/security/core/tests/common/security_config_test_utils.h b/src/security/core/tests/common/security_config_test_utils.h index 3cf20de..770c979 100644 --- a/src/security/core/tests/common/security_config_test_utils.h +++ b/src/security/core/tests/common/security_config_test_utils.h @@ -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); diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index 3f94a85..99a4eaf 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -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; +} diff --git a/src/security/core/tests/common/test_utils.h b/src/security/core/tests/common/test_utils.h index 919affe..5fb9ccb 100644 --- a/src/security/core/tests/common/test_utils.h +++ b/src/security/core/tests/common/test_utils.h @@ -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_ */ diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 186944c..fb7386f 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -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:+,}" "" @@ -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)