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)