Access control tests

Add test cases for the join_access_control governance setting and for
the access control plugin check_create_ and check_remote_ hooks,
using a wrapper plugin that simulates failure for each of these,
to test the DDSI integration with the access control plugin.
This commit also contains fixes for:
- an assert on DDS_RETCODE_OK in dds_create_reader and
dds_create_writer that cased the application to terminate in case
creation of a reader or writer is not allowed by security
- do not match a proxy reader that has the 'relay_only' set to
true, which is currently unsupported

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
This commit is contained in:
Dennis Potman 2020-04-14 20:25:20 +02:00 committed by eboasson
parent 080514d45a
commit 19bc6f33cc
21 changed files with 1022 additions and 437 deletions

View file

@ -68,7 +68,7 @@ set(security_core_test_sources
)
if(ENABLE_SSL)
add_wrapper(access_control "")
add_wrapper(access_control dds_security_ac)
add_wrapper(authentication dds_security_auth)
add_wrapper(cryptography dds_security_crypto)
@ -108,7 +108,7 @@ configure_file("common/config_env.h.in" "common/config_env.h")
target_link_libraries(cunit_security_core PRIVATE ddsc security_api SecurityCoreTests)
if(ENABLE_SSL)
target_link_libraries(cunit_security_core PRIVATE dds_security_auth dds_security_ac dds_security_crypto dds_security_authentication_wrapper dds_security_cryptography_wrapper)
target_link_libraries(cunit_security_core PRIVATE dds_security_auth dds_security_ac dds_security_crypto dds_security_access_control_wrapper dds_security_authentication_wrapper dds_security_cryptography_wrapper)
target_link_libraries(cunit_security_core PRIVATE OpenSSL::SSL)
endif()
target_include_directories(cunit_security_core PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")

View file

@ -47,13 +47,13 @@ static const char *config =
" </Discovery>"
" <DDSSecurity>"
" <Authentication>"
" <Library finalizeFunction=\"finalize_authentication\" initFunction=\"init_authentication\"/>"
" <Library finalizeFunction=\"finalize_test_authentication_wrapped\" initFunction=\"init_test_authentication_wrapped\" path=\"" WRAPPERLIB_PATH("dds_security_authentication_wrapper") "\"/>"
" <IdentityCertificate>data:,${TEST_IDENTITY_CERTIFICATE}</IdentityCertificate>"
" <PrivateKey>data:,${TEST_IDENTITY_PRIVATE_KEY}</PrivateKey>"
" <IdentityCA>data:,${TEST_IDENTITY_CA_CERTIFICATE}</IdentityCA>"
" </Authentication>"
" <AccessControl>"
" <Library finalizeFunction=\"finalize_access_control\" initFunction=\"init_access_control\"/>"
" <Library initFunction=\"${ACCESS_CONTROL_INIT:-init_test_access_control_wrapped}\" finalizeFunction=\"${ACCESS_CONTROL_FINI:-finalize_test_access_control_wrapped}\" path=\"" WRAPPERLIB_PATH("dds_security_access_control_wrapper") "\"/>"
" ${INCL_GOV:+<Governance><![CDATA[}${TEST_GOVERNANCE}${INCL_GOV:+]]></Governance>}"
" ${INCL_PERM_CA:+<PermissionsCA>}${TEST_PERMISSIONS_CA}${INCL_PERM_CA:+</PermissionsCA>}"
" ${INCL_PERM:+<Permissions><![CDATA[}${TEST_PERMISSIONS}${INCL_PERM:+]]></Permissions>}"
@ -65,19 +65,22 @@ static const char *config =
"</Domain>";
#define MAX_DOMAINS 10
#define DDS_DOMAINID
#define DDS_DOMAINID 0
#define PF_F "file:"
#define PF_D "data:,"
static dds_entity_t g_domain[MAX_DOMAINS];
static dds_entity_t g_participant[MAX_DOMAINS];
static dds_entity_t g_pubsub[MAX_DOMAINS];
static dds_entity_t g_topic[MAX_DOMAINS];
static uint32_t g_topic_nr = 0;
static void access_control_init(
const char * id_certs[], const char * id_keys[], const char * id_ca[], bool exp_pp_fail[], size_t n_nodes,
bool incl_gov, const char * gov,
bool incl_perm, const char * perm,
bool incl_ca, const char * ca)
size_t n_nodes,
const char * id_certs[], const char * id_keys[], const char * id_ca[], bool exp_pp_fail[],
const char * ac_init_fns[], const char * ac_fini_fns[],
bool incl_gov[], const char * gov[],
bool incl_perm[], const char * perm[],
bool incl_ca[], const char * ca[])
{
CU_ASSERT_FATAL (n_nodes <= MAX_DOMAINS);
for (size_t i = 0; i < n_nodes; i++)
@ -86,12 +89,14 @@ static void access_control_init(
{ "TEST_IDENTITY_CERTIFICATE", id_certs[i], 1 },
{ "TEST_IDENTITY_PRIVATE_KEY", id_keys[i], 1 },
{ "TEST_IDENTITY_CA_CERTIFICATE", id_ca[i], 1 },
{ "INCL_GOV", incl_gov ? "1" : "", 2 },
{ "INCL_PERM", incl_perm ? "1" : "", 2 },
{ "INCL_PERM_CA", incl_ca ? "1" : "", 2 },
{ "TEST_GOVERNANCE", gov, 1 },
{ "TEST_PERMISSIONS", perm, 1 },
{ "TEST_PERMISSIONS_CA", ca, 1 },
{ "ACCESS_CONTROL_INIT", ac_init_fns ? ac_init_fns[i] : NULL, 1 },
{ "ACCESS_CONTROL_FINI", ac_fini_fns ? ac_fini_fns[i] : NULL, 1 },
{ "INCL_GOV", incl_gov[i] ? "1" : "", 2 },
{ "INCL_PERM", incl_perm[i] ? "1" : "", 2 },
{ "INCL_PERM_CA", incl_ca[i] ? "1" : "", 2 },
{ "TEST_GOVERNANCE", gov[i], 1 },
{ "TEST_PERMISSIONS", perm[i], 1 },
{ "TEST_PERMISSIONS_CA", ca[i], 1 },
{ NULL, NULL, 0 }
};
char *conf = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars);
@ -109,9 +114,6 @@ static void access_control_fini(size_t n)
CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain[i]), DDS_RETCODE_OK);
}
#define PF_F "file:"
#define PF_D "data:,"
#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")
@ -149,14 +151,18 @@ CU_Theory((const char * test_descr, const char * gov, const char * perm, const c
ddssec_access_control, config_parameters_file)
{
print_test_msg ("running test config_parameters_file: %s\n", test_descr);
bool has_gov = incl_empty_els || strlen (gov);
bool has_perm = incl_empty_els || strlen (perm);
bool has_ca = incl_empty_els || strlen (ca);
access_control_init (
2,
(const char *[]) { TEST_IDENTITY1_CERTIFICATE, TEST_IDENTITY1_CERTIFICATE },
(const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY },
(const char *[]) { TEST_IDENTITY_CA1_CERTIFICATE, TEST_IDENTITY_CA1_CERTIFICATE },
(bool []) { exp_fail, exp_fail }, 2,
incl_empty_els || strlen (gov), gov,
incl_empty_els || strlen (perm), perm,
incl_empty_els || strlen (ca), ca);
(bool []) { exp_fail, exp_fail }, NULL, NULL,
(bool []) { has_gov, has_gov }, (const char *[]) { gov, gov },
(bool []) { has_perm, has_perm }, (const char *[]) { perm, perm },
(bool []) { has_ca, has_ca }, (const char *[]) { ca, ca });
access_control_fini (2);
}
@ -170,8 +176,8 @@ CU_TheoryDataPoints(ddssec_access_control, permissions_expiry) = {
/* | */"valid -1 minute until now",
/* | | */"1s valid, create pp after 1100ms",
/* | | | */"node 2 permissions expired",
/* | | | | */"node 1 3s valid, write/read for 10s",
/* | | | | | */"node 2 3s valid, write/read for 10s"),
/* | | | | */"node 1 4s valid, write/read for 10s",
/* | | | | | */"node 2 4s valid, write/read for 10s"),
CU_DataPoints(int32_t, 0, -M(1), 0, 0, 0, 0), /* node 1 permissions not before (offset from local time) */
CU_DataPoints(int32_t, M(1), 0, S(1), D(1), S(4), D(1)), /* node 1 permissions not after (offset from local time) */
CU_DataPoints(int32_t, 0, -M(1), 0, -D(1), 0, 0), /* node 2 permissions not before (offset from local time) */
@ -179,14 +185,18 @@ CU_TheoryDataPoints(ddssec_access_control, permissions_expiry) = {
CU_DataPoints(uint32_t, 0, 0, 1100, 0, 0, 0), /* delay (ms) after generating permissions */
CU_DataPoints(bool, false, true, true, false, false, false), /* expect pp 1 create failure */
CU_DataPoints(bool, false, true, true, true, false, false), /* expect pp 2 create failure */
CU_DataPoints(uint32_t, 1, 0, 0, 0, 10000, 10000), /* write/read data during x ms */
CU_DataPoints(uint32_t, 1, 0, 0, 0, 10000, 10000), /* write/read data during x ms */
CU_DataPoints(bool, false, false, false, false, true, true), /* expect read data failure */
};
#undef S
#undef D
#undef H
#undef M
CU_Theory(
(const char * test_descr,
int32_t perm1_not_before, int32_t perm1_not_after, int32_t perm2_not_before, int32_t perm2_not_after,
uint32_t delay_perm, bool exp_pp1_fail, bool exp_pp2_fail, uint32_t write_read_dur, bool exp_read_fail),
ddssec_access_control, permissions_expiry, .timeout=20)
ddssec_access_control, permissions_expiry, .timeout=30)
{
print_test_msg ("running test permissions_expiry: %s\n", test_descr);
@ -195,32 +205,38 @@ CU_Theory(
/* 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, D(1));
id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, D(1), &id1_subj);
id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, D(1), &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, now + DDS_SECS(perm1_not_before), now + DDS_SECS(perm1_not_after), perm_topic, perm_topic, NULL),
get_permissions_grant ("id2", id2_subj, now + DDS_SECS(perm2_not_before), now + DDS_SECS(perm2_not_after), perm_topic, perm_topic, NULL) };
get_permissions_grant ("id1", id1_subj, NULL, now + DDS_SECS(perm1_not_before), now + DDS_SECS(perm1_not_after), perm_topic, perm_topic, NULL),
get_permissions_grant ("id2", id2_subj, NULL, now + DDS_SECS(perm2_not_before), now + DDS_SECS(perm2_not_after), perm_topic, perm_topic, NULL) };
char * perm_config = get_permissions_config (grants, 2, true);
dds_sleepfor (DDS_MSECS (delay_perm));
const char * def_gov = PF_F COMMON_ETC_PATH("default_governance.p7s");
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 []) { exp_pp1_fail, exp_pp2_fail }, 2,
true, PF_F COMMON_ETC_PATH("default_governance.p7s"),
true, perm_config,
true, PF_F COMMON_ETC_PATH("default_permissions_ca.pem"));
(bool []) { exp_pp1_fail, exp_pp2_fail }, NULL, NULL,
(bool []) { true, true }, (const char *[]) { def_gov, def_gov },
(bool []) { true, true }, (const char *[]) { perm_config, perm_config },
(bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca });
if (write_read_dur > 0)
{
dds_entity_t wr = 0, rd = 0;
rd_wr_init (g_participant[0], &g_pubsub[0], &g_topic[0], &wr, g_participant[1], &g_pubsub[1], &g_topic[1], &rd, topic_name);
dds_entity_t pub, sub;
dds_entity_t topic0, topic1;
rd_wr_init (g_participant[0], &pub, &topic0, &wr, g_participant[1], &sub, &topic1, &rd, topic_name);
sync_writer_to_readers(g_participant[0], wr, 1);
write_read_for (wr, g_participant[1], rd, DDS_MSECS (write_read_dur), false, exp_read_fail);
}
@ -236,9 +252,6 @@ CU_Theory(
ddsrt_free (id1);
ddsrt_free (id2);
}
#undef D
#undef H
#undef M
#define N_RD 1 // N_RD > 1 not yet implemented
@ -256,9 +269,10 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20)
// 1st node used as reader, other nodes as writer
print_test_msg ("creating permissions grants\n");
const char *id[N_NODES], *pk[N_NODES], *ca_list[N_NODES];
const char *id[N_NODES], *pk[N_NODES], *ca_list[N_NODES], *gov[N_NODES], *perm_conf[N_NODES], *perm_ca[N_NODES];
char * id_subj[N_NODES], *grants[N_NODES];
bool exp_fail[N_NODES];
bool exp_fail[N_NODES], incl_el[N_NODES];
for (int i = 0; i < N_NODES; i++)
{
char *id_name;
@ -267,20 +281,25 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20)
ca_list[i] = ca;
id[i] = generate_identity (ca_list[i], TEST_IDENTITY_CA1_PRIVATE_KEY, id_name, pk[i], 0, 3600, &id_subj[i]);
exp_fail[i] = false;
gov[i] = PF_F COMMON_ETC_PATH ("default_governance.p7s");
perm_ca[i] = PF_F COMMON_ETC_PATH ("default_permissions_ca.pem");
incl_el[i] = true;
dds_duration_t v = DDS_SECS(i < N_RD ? 3600 : PERM_EXP_BASE + 2 * i); /* readers should not expire */
dds_time_t t_exp = ddsrt_time_add_duration (t_perm, v);
if (i >= N_RD)
print_test_msg ("w[%d] grant expires at %d.%06d\n", i - N_RD, (int32_t) (t_exp / DDS_NSECS_IN_SEC), (int32_t) (t_exp % DDS_NSECS_IN_SEC) / 1000);
grants[i] = get_permissions_grant (id_name, id_subj[i], t_perm, t_exp, perm_topic, perm_topic, NULL);
grants[i] = get_permissions_grant (id_name, id_subj[i], NULL, t_perm, t_exp, perm_topic, perm_topic, NULL);
ddsrt_free (id_name);
}
char * perm_config = get_permissions_config (grants, N_NODES, true);
char * perm_config_str = get_permissions_config (grants, N_NODES, true);
for (int i = 0; i < N_NODES; i++)
perm_conf[i] = perm_config_str;
access_control_init (
id, pk, ca_list, exp_fail, N_NODES,
true, PF_F COMMON_ETC_PATH ("default_governance.p7s"),
true, perm_config,
true, PF_F COMMON_ETC_PATH ("default_permissions_ca.pem"));
N_NODES,
id, pk, ca_list, exp_fail, NULL, NULL,
incl_el, gov, incl_el, perm_conf, incl_el, perm_ca);
dds_qos_t * qos = dds_create_qos ();
CU_ASSERT_FATAL (qos != NULL);
@ -374,6 +393,156 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20)
}
ddsrt_free (ca);
ddsrt_free (perm_topic);
ddsrt_free (perm_config);
ddsrt_free (perm_config_str);
}
#undef N_RD
#undef N_WR
#undef N_NODES
#undef PERM_EXP_BASE
#define na false
CU_TheoryDataPoints(ddssec_access_control, hooks) = {
CU_DataPoints(const char *,
/* */"init_test_access_control_local_participant_not_allowed",
/* | */"init_test_access_control_local_topic_not_allowed",
/* | | */"init_test_access_control_local_publishing_not_allowed",
/* | | | */"init_test_access_control_local_subscribing_not_allowed",
/* | | | | */"init_test_access_control_remote_permissions_invalidate",
/* | | | | | */"init_test_access_control_remote_participant_not_allowed",
/* | | | | | | */"init_test_access_control_remote_topic_not_allowed",
/* | | | | | | | */"init_test_access_control_remote_writer_not_allowed",
/* | | | | | | | | */"init_test_access_control_remote_reader_not_allowed",
/* | | | | | | | | | */"init_test_access_control_remote_reader_relay_only"),
CU_DataPoints(bool, true, false, false, false, false, false, false, false, false, false), // exp_pp_fail
CU_DataPoints(bool, na, true, false, false, false, false, false, false, false, false), // exp_local_topic_fail
CU_DataPoints(bool, na, false, false, false, false, false, false, false, false, false), // exp_remote_topic_fail
CU_DataPoints(bool, na, na, true, false, false, false, false, false, false, false), // exp_wr_fail
CU_DataPoints(bool, na, na, false, true, false, false, false, false, false, false), // exp_rd_fail
CU_DataPoints(bool, na, na, na, na, true, true, true, false, true, true), // exp_wr_rd_sync_fail
CU_DataPoints(bool, na, na, false, na, true, true, true, true, false, false), // exp_rd_wr_sync_fail
};
#undef na
CU_Theory(
(const char * init_fn, bool exp_pp_fail, bool exp_local_topic_fail, bool exp_remote_topic_fail, bool exp_wr_fail, bool exp_rd_fail, bool exp_wr_rd_sync_fail, bool exp_rd_wr_sync_fail),
ddssec_access_control, hooks, .timeout=40)
{
print_test_msg ("running test access_control_hooks: %s\n", init_fn);
const char * def_gov = PF_F COMMON_ETC_PATH("default_governance.p7s");
const char * def_perm = PF_F COMMON_ETC_PATH("default_permissions.p7s");
const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem");
access_control_init (
2,
(const char *[]) { TEST_IDENTITY1_CERTIFICATE, TEST_IDENTITY1_CERTIFICATE },
(const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY },
(const char *[]) { TEST_IDENTITY_CA1_CERTIFICATE, TEST_IDENTITY_CA1_CERTIFICATE },
(bool []) { exp_pp_fail, false },
(const char *[]) { init_fn, "init_test_access_control_wrapped" }, (const char *[]) { "finalize_test_access_control_not_allowed", "finalize_test_access_control_wrapped" },
(bool []) { true, true, true }, (const char *[]) { def_gov, def_gov },
(bool []) { true, true, true }, (const char *[]) { def_perm, def_perm },
(bool []) { true, true, true }, (const char *[]) { def_perm_ca, def_perm_ca });
if (!exp_pp_fail)
{
dds_entity_t lwr = 0, rwr = 0, lrd = 0, rrd = 0;
dds_entity_t ltopic[2], rtopic[2];
dds_entity_t lpub, lsub, rpub, rsub;
char topic_name[100];
// Local writer, remote reader
create_topic_name (AC_WRAPPER_TOPIC_PREFIX, g_topic_nr++, topic_name, sizeof (topic_name));
rd_wr_init_fail (
g_participant[0], &lpub, &ltopic[0], &lwr,
g_participant[1], &rsub, &rtopic[0], &rrd,
topic_name, exp_local_topic_fail, exp_wr_fail, exp_remote_topic_fail, false);
if (!exp_local_topic_fail && !exp_remote_topic_fail && !exp_wr_fail)
sync_writer_to_readers (g_participant[0], lwr, exp_wr_rd_sync_fail ? 0 : 1);
// Local reader, remote writer
create_topic_name (AC_WRAPPER_TOPIC_PREFIX, g_topic_nr++, topic_name, sizeof (topic_name));
rd_wr_init_fail (
g_participant[1], &rpub, &rtopic[1], &rwr,
g_participant[0], &lsub, &ltopic[1], &lrd,
topic_name, exp_remote_topic_fail, false, exp_local_topic_fail, exp_rd_fail);
if (!exp_local_topic_fail && !exp_remote_topic_fail && !exp_rd_fail)
sync_reader_to_writers (g_participant[0], lrd, exp_rd_wr_sync_fail ? 0 : 1);
}
access_control_fini (2);
}
#define na false
CU_TheoryDataPoints(ddssec_access_control, join_access_control) = {
CU_DataPoints(const char *,
/* */"no join access control",
/* | */"join access control pp1, valid",
/* | | */"join access control pp1 and pp2, valid",
/* | | | */"join access control pp1, invalid",
/* | | | | */"join access control pp1 and pp2, invalid"),
CU_DataPoints(bool, false, true, true, true, true), /* join access control pp 1 enabled */
CU_DataPoints(bool, false, false, true, false, true), /* join access control pp 2 enabled */
CU_DataPoints(bool, false, false, false, true, true), /* permissions pp 1 invalid */
CU_DataPoints(bool, false, false, false, false, true), /* permissions pp 2 invalid */
CU_DataPoints(bool, false, false, false, true, true), /* expect pp 1 create failure */
CU_DataPoints(bool, false, false, false, false, true), /* expect pp 2 create failure */
CU_DataPoints(bool, false, false, false, na, na), /* expect handshake failure */
};
#undef na
CU_Theory(
(const char * test_descr, bool join_ac_pp1, bool join_ac_pp2, bool perm_inv_pp1, bool perm_inv_pp2, bool exp_pp1_fail, bool exp_pp2_fail, bool exp_hs_fail),
ddssec_access_control, join_access_control, .timeout=30)
{
print_test_msg ("running test join_access_control: %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, perm_inv_pp1 ? "99" : NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL),
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);
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 []) { exp_pp1_fail, exp_pp2_fail }, NULL, NULL,
(bool []) { true, true }, (const char *[]) { gov_config_pp1, gov_config_pp2 },
(bool []) { true, true }, (const char *[]) { perm_config, perm_config },
(bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca });
if (!exp_pp1_fail && !exp_pp2_fail)
validate_handshake (DDS_DOMAINID, exp_hs_fail, NULL, NULL, NULL);
access_control_fini (2);
ddsrt_free (gov_config_pp1);
ddsrt_free (gov_config_pp2);
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);
}

View file

@ -309,8 +309,8 @@ CU_Theory(
dds_time_t now = dds_time ();
char * grants[] = {
get_permissions_grant ("id1", id1_subj, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL),
get_permissions_grant ("id2", id2_subj, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL) };
get_permissions_grant ("id1", id1_subj, NULL, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL),
get_permissions_grant ("id2", id2_subj, NULL, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL) };
char * perm_config = get_permissions_config (grants, 2, true);
authentication_init (id1, ID1K, ca, id2, ID1K, ca, NULL, perm_config, id1_local_fail, id2_local_fail);
validate_handshake (DDS_DOMAINID1, id1_local_fail, NULL, NULL, NULL);
@ -318,6 +318,7 @@ CU_Theory(
if (write_read_dur > 0)
{
rd_wr_init (g_participant1, &g_pub, &g_pub_tp, &g_wr, g_participant2, &g_sub, &g_sub_tp, &g_rd, topic_name);
sync_writer_to_readers(g_participant1, g_wr, 1);
write_read_for (g_wr, g_participant2, g_rd, DDS_MSECS (write_read_dur), false, exp_read_fail);
}
authentication_fini (!id1_local_fail, !id2_local_fail);

View file

@ -20,18 +20,49 @@
#include "dds/security/core/dds_security_utils.h"
#include "access_control_wrapper.h"
int init_access_control(const char *argument, void **context, struct ddsi_domaingv *gv);
int finalize_access_control(void *context);
enum ac_plugin_mode {
PLUGIN_MODE_ALL_OK,
PLUGIN_MODE_WRAPPED,
PLUGIN_MODE_NOT_ALLOWED,
PLUGIN_MODE_MISSING_FUNC
};
enum ac_plugin_not_allowed {
NOT_ALLOWED_ID_LOCAL_PP,
NOT_ALLOWED_ID_LOCAL_TOPIC,
NOT_ALLOWED_ID_LOCAL_PUB,
NOT_ALLOWED_ID_LOCAL_SUB,
NOT_ALLOWED_ID_REMOTE_PERM,
NOT_ALLOWED_ID_REMOTE_PP,
NOT_ALLOWED_ID_REMOTE_TOPIC,
NOT_ALLOWED_ID_REMOTE_WRITER,
NOT_ALLOWED_ID_REMOTE_READER,
NOT_ALLOWED_ID_REMOTE_READER_RELAY_ONLY
};
#define NOT_ALLOWED_LOCAL_PP (1u << NOT_ALLOWED_ID_LOCAL_PP)
#define NOT_ALLOWED_LOCAL_TOPIC (1u << NOT_ALLOWED_ID_LOCAL_TOPIC)
#define NOT_ALLOWED_LOCAL_PUB (1u << NOT_ALLOWED_ID_LOCAL_PUB)
#define NOT_ALLOWED_LOCAL_SUB (1u << NOT_ALLOWED_ID_LOCAL_SUB)
#define NOT_ALLOWED_REMOTE_PERM (1u << NOT_ALLOWED_ID_REMOTE_PERM)
#define NOT_ALLOWED_REMOTE_PP (1u << NOT_ALLOWED_ID_REMOTE_PP)
#define NOT_ALLOWED_REMOTE_TOPIC (1u << NOT_ALLOWED_ID_REMOTE_TOPIC)
#define NOT_ALLOWED_REMOTE_WRITER (1u << NOT_ALLOWED_ID_REMOTE_WRITER)
#define NOT_ALLOWED_REMOTE_READER (1u << NOT_ALLOWED_ID_REMOTE_READER)
#define NOT_ALLOWED_REMOTE_READER_RELAY_ONLY (1u << NOT_ALLOWED_ID_REMOTE_READER_RELAY_ONLY)
/**
* Implementation structure for storing encapsulated members of the instance
* while giving only the interface definition to user
*/
struct dds_security_access_control_impl {
dds_security_access_control base;
dds_security_access_control *instance;
enum ac_plugin_mode mode;
uint32_t not_allowed_mask;
};
static DDS_Security_PermissionsHandle validate_local_permissions(
@ -42,14 +73,16 @@ static DDS_Security_PermissionsHandle validate_local_permissions(
const DDS_Security_Qos *participant_qos,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(auth_plugin);
DDSRT_UNUSED_ARG(auth_plugin);
DDSRT_UNUSED_ARG(identity);
DDSRT_UNUSED_ARG(domain_id);
DDSRT_UNUSED_ARG(participant_qos);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return 1;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->validate_local_permissions(impl->instance, auth_plugin, identity, domain_id, participant_qos, ex);
default:
return 1;
}
}
static DDS_Security_PermissionsHandle validate_remote_permissions(
@ -61,31 +94,54 @@ static DDS_Security_PermissionsHandle validate_remote_permissions(
const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(auth_plugin);
DDSRT_UNUSED_ARG(local_identity_handle);
DDSRT_UNUSED_ARG(remote_identity_handle);
DDSRT_UNUSED_ARG(remote_permissions_token);
DDSRT_UNUSED_ARG(remote_credential_token);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return 0;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_NOT_ALLOWED:
if (impl->not_allowed_mask & NOT_ALLOWED_REMOTE_PERM)
{
ex->code = 1;
ex->message = ddsrt_strdup ("not_allowed: validate_remote_permissions");
return 0;
}
/* fall through */
case PLUGIN_MODE_WRAPPED:
return impl->instance->validate_remote_permissions(impl->instance, auth_plugin, local_identity_handle, remote_identity_handle,
remote_permissions_token, remote_credential_token, ex);
default:
return 0;
}
}
static DDS_Security_boolean check_create_participant( dds_security_access_control *instance,
static DDS_Security_boolean check_create_participant(
dds_security_access_control *instance,
const DDS_Security_PermissionsHandle permissions_handle,
const DDS_Security_DomainId domain_id,
const DDS_Security_Qos *participant_qos,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(domain_id);
DDSRT_UNUSED_ARG(participant_qos);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_NOT_ALLOWED:
if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_PP)
{
ex->code = 1;
ex->message = ddsrt_strdup ("not_allowed: check_create_participant");
return false;
}
/* fall through */
case PLUGIN_MODE_WRAPPED:
return impl->instance->check_create_participant(impl->instance, permissions_handle, domain_id, participant_qos, ex);
default:
return true;
}
}
static DDS_Security_boolean check_create_datawriter( dds_security_access_control *instance,
static DDS_Security_boolean check_create_datawriter(
dds_security_access_control *instance,
const DDS_Security_PermissionsHandle permissions_handle,
const DDS_Security_DomainId domain_id,
const char *topic_name,
@ -94,18 +150,30 @@ static DDS_Security_boolean check_create_datawriter( dds_security_access_control
const DDS_Security_DataTags *data_tag,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(domain_id);
DDSRT_UNUSED_ARG(topic_name);
DDSRT_UNUSED_ARG(writer_qos);
DDSRT_UNUSED_ARG(partition);
DDSRT_UNUSED_ARG(data_tag);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_NOT_ALLOWED:
if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_PUB)
{
if (topic_name && strncmp (topic_name, AC_WRAPPER_TOPIC_PREFIX, strlen (AC_WRAPPER_TOPIC_PREFIX)) == 0)
{
ex->code = 1;
ex->message = ddsrt_strdup ("not_allowed: check_create_datawriter");
return false;
}
}
/* fall through */
case PLUGIN_MODE_WRAPPED:
return impl->instance->check_create_datawriter(impl->instance, permissions_handle, domain_id, topic_name, writer_qos, partition, data_tag, ex);
default:
return true;
}
}
static DDS_Security_boolean check_create_datareader( dds_security_access_control *instance,
static DDS_Security_boolean check_create_datareader(
dds_security_access_control *instance,
const DDS_Security_PermissionsHandle permissions_handle,
const DDS_Security_DomainId domain_id,
const char *topic_name,
@ -114,31 +182,50 @@ static DDS_Security_boolean check_create_datareader( dds_security_access_control
const DDS_Security_DataTags *data_tag,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(domain_id);
DDSRT_UNUSED_ARG(topic_name);
DDSRT_UNUSED_ARG(reader_qos);
DDSRT_UNUSED_ARG(partition);
DDSRT_UNUSED_ARG(data_tag);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_NOT_ALLOWED:
if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_SUB)
{
ex->code = 1;
ex->message = ddsrt_strdup ("not_allowed: check_create_datareader");
return false;
}
/* fall through */
case PLUGIN_MODE_WRAPPED:
return impl->instance->check_create_datareader(impl->instance, permissions_handle, domain_id, topic_name, reader_qos, partition, data_tag, ex);
default:
return true;
}
}
static DDS_Security_boolean check_create_topic( dds_security_access_control *instance,
static DDS_Security_boolean check_create_topic(
dds_security_access_control *instance,
const DDS_Security_PermissionsHandle permissions_handle,
const DDS_Security_DomainId domain_id,
const char *topic_name,
const DDS_Security_Qos *qos,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(domain_id);
DDSRT_UNUSED_ARG(topic_name);
DDSRT_UNUSED_ARG(qos);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_NOT_ALLOWED:
if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_TOPIC)
{
ex->code = 1;
ex->message = ddsrt_strdup ("not_allowed: check_create_topic");
return false;
}
/* fall through */
case PLUGIN_MODE_WRAPPED:
return impl->instance->check_create_topic(impl->instance, permissions_handle, domain_id, topic_name, qos, ex);
default:
return true;
}
}
static DDS_Security_boolean check_local_datawriter_register_instance(
@ -148,12 +235,16 @@ static DDS_Security_boolean check_local_datawriter_register_instance(
const DDS_Security_DynamicData *key,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(writer);
DDSRT_UNUSED_ARG(key);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->check_local_datawriter_register_instance(impl->instance, permissions_handle, writer, key, ex);
default:
return true;
}
}
static DDS_Security_boolean check_local_datawriter_dispose_instance(
@ -163,69 +254,137 @@ static DDS_Security_boolean check_local_datawriter_dispose_instance(
const DDS_Security_DynamicData key,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(writer);
DDSRT_UNUSED_ARG(key);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->check_local_datawriter_dispose_instance(impl->instance, permissions_handle, writer, key, ex);
default:
return true;
}
}
static DDS_Security_boolean check_remote_participant( dds_security_access_control *instance,
static DDS_Security_boolean check_remote_participant(
dds_security_access_control *instance,
const DDS_Security_PermissionsHandle permissions_handle,
const DDS_Security_DomainId domain_id,
const DDS_Security_ParticipantBuiltinTopicDataSecure *participant_data,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(domain_id);
DDSRT_UNUSED_ARG(participant_data);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_NOT_ALLOWED:
if (impl->not_allowed_mask & NOT_ALLOWED_REMOTE_PP)
{
ex->code = 1;
ex->message = ddsrt_strdup ("not_allowed: check_remote_participant");
return false;
}
/* fall through */
case PLUGIN_MODE_WRAPPED:
return impl->instance->check_remote_participant(impl->instance, permissions_handle, domain_id, participant_data, ex);
default:
return true;
}
}
static DDS_Security_boolean check_remote_datawriter( dds_security_access_control *instance,
static DDS_Security_boolean check_remote_datawriter(
dds_security_access_control *instance,
const DDS_Security_PermissionsHandle permissions_handle,
const DDS_Security_DomainId domain_id,
const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(domain_id);
DDSRT_UNUSED_ARG(publication_data);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_NOT_ALLOWED:
if (impl->not_allowed_mask & NOT_ALLOWED_REMOTE_WRITER)
{
ex->code = 1;
ex->message = ddsrt_strdup ("not_allowed: check_remote_datawriter");
return false;
}
/* fall through */
case PLUGIN_MODE_WRAPPED:
return impl->instance->check_remote_datawriter(impl->instance, permissions_handle, domain_id, publication_data, ex);
default:
return true;
}
}
static DDS_Security_boolean check_remote_datareader( dds_security_access_control *instance,
static DDS_Security_boolean check_remote_datareader(
dds_security_access_control *instance,
const DDS_Security_PermissionsHandle permissions_handle,
const DDS_Security_DomainId domain_id,
const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data,
DDS_Security_boolean *relay_only, DDS_Security_SecurityException *ex)
DDS_Security_boolean *relay_only,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(domain_id);
DDSRT_UNUSED_ARG(subscription_data);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
*relay_only = false;
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_NOT_ALLOWED:
if (impl->not_allowed_mask & NOT_ALLOWED_REMOTE_READER)
{
if (subscription_data->topic_name && strncmp (subscription_data->topic_name, AC_WRAPPER_TOPIC_PREFIX, strlen (AC_WRAPPER_TOPIC_PREFIX)) == 0)
{
ex->code = 1;
ex->message = ddsrt_strdup ("not_allowed: check_remote_datareader");
return false;
}
}
/* fall through */
case PLUGIN_MODE_WRAPPED:
{
bool ret;
if ((ret = impl->instance->check_remote_datareader(impl->instance, permissions_handle, domain_id, subscription_data, relay_only, ex)))
{
/* Only relay_only for the user reader, not the builtin ones. */
if (impl->mode == PLUGIN_MODE_NOT_ALLOWED && impl->not_allowed_mask & NOT_ALLOWED_REMOTE_READER_RELAY_ONLY)
{
if (subscription_data->topic_name && strncmp (subscription_data->topic_name, AC_WRAPPER_TOPIC_PREFIX, strlen (AC_WRAPPER_TOPIC_PREFIX)) == 0)
*relay_only = true;
}
}
return ret;
}
default:
*relay_only = false;
return true;
}
}
static DDS_Security_boolean check_remote_topic( dds_security_access_control *instance,
static DDS_Security_boolean check_remote_topic(
dds_security_access_control *instance,
const DDS_Security_PermissionsHandle permissions_handle,
const DDS_Security_DomainId domain_id,
const DDS_Security_TopicBuiltinTopicData *topic_data,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(domain_id);
DDSRT_UNUSED_ARG(topic_data);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_NOT_ALLOWED:
if (impl->not_allowed_mask & NOT_ALLOWED_REMOTE_TOPIC)
{
ex->code = 1;
ex->message = ddsrt_strdup ("not_allowed: check_remote_topic");
return false;
}
/* fall through */
case PLUGIN_MODE_WRAPPED:
return impl->instance->check_remote_topic(impl->instance, permissions_handle, domain_id, topic_data, ex);
default:
return true;
}
}
static DDS_Security_boolean check_local_datawriter_match(
@ -236,13 +395,16 @@ static DDS_Security_boolean check_local_datawriter_match(
const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(writer_permissions_handle);
DDSRT_UNUSED_ARG(reader_permissions_handle);
DDSRT_UNUSED_ARG(publication_data);
DDSRT_UNUSED_ARG(subscription_data);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->check_local_datawriter_match(impl->instance, writer_permissions_handle, reader_permissions_handle, publication_data, subscription_data, ex);
default:
return true;
}
}
static DDS_Security_boolean check_local_datareader_match(
@ -253,13 +415,16 @@ static DDS_Security_boolean check_local_datareader_match(
const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(reader_permissions_handle);
DDSRT_UNUSED_ARG(writer_permissions_handle);
DDSRT_UNUSED_ARG(subscription_data);
DDSRT_UNUSED_ARG(publication_data);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->check_local_datareader_match(impl->instance, reader_permissions_handle, writer_permissions_handle, subscription_data, publication_data, ex);
default:
return true;
}
}
static DDS_Security_boolean check_remote_datawriter_register_instance(
@ -271,14 +436,16 @@ static DDS_Security_boolean check_remote_datawriter_register_instance(
const DDS_Security_InstanceHandle instance_handle,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(reader);
DDSRT_UNUSED_ARG(publication_handle);
DDSRT_UNUSED_ARG(key);
DDSRT_UNUSED_ARG(instance_handle);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->check_remote_datawriter_register_instance(impl->instance, permissions_handle, reader, publication_handle, key, instance_handle, ex);
default:
return true;
}
}
static DDS_Security_boolean check_remote_datawriter_dispose_instance(
@ -289,13 +456,16 @@ static DDS_Security_boolean check_remote_datawriter_dispose_instance(
const DDS_Security_DynamicData key,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(reader);
DDSRT_UNUSED_ARG(publication_handle);
DDSRT_UNUSED_ARG(key);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->check_remote_datawriter_dispose_instance(impl->instance, permissions_handle, reader, publication_handle, key, ex);
default:
return true;
}
}
static DDS_Security_boolean get_permissions_token(
@ -304,12 +474,18 @@ static DDS_Security_boolean get_permissions_token(
const DDS_Security_PermissionsHandle handle,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(handle);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
memset(permissions_token, 0, sizeof(*permissions_token));
permissions_token->class_id = ddsrt_strdup("");
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->get_permissions_token(impl->instance, permissions_token, handle, ex);
default:
memset(permissions_token, 0, sizeof(*permissions_token));
permissions_token->class_id = ddsrt_strdup ("");
return true;
}
}
static DDS_Security_boolean get_permissions_credential_token(
@ -318,31 +494,51 @@ static DDS_Security_boolean get_permissions_credential_token(
const DDS_Security_PermissionsHandle handle,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_credential_token);
DDSRT_UNUSED_ARG(handle);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->get_permissions_credential_token(impl->instance, permissions_credential_token, handle, ex);
default:
return true;
}
}
static DDS_Security_boolean set_listener( dds_security_access_control *instance,
static DDS_Security_boolean set_listener(
dds_security_access_control *instance,
const dds_security_access_control_listener *listener,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(listener);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->set_listener (impl->instance, listener, ex);
default:
return true;
}
}
static DDS_Security_boolean return_permissions_token( dds_security_access_control *instance,
static DDS_Security_boolean return_permissions_token(
dds_security_access_control *instance,
const DDS_Security_PermissionsToken *token,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
ddsrt_free (token->class_id);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->return_permissions_token (impl->instance, token, ex);
default:
ddsrt_free (token->class_id);
return true;
}
}
static DDS_Security_boolean return_permissions_credential_token(
@ -350,10 +546,16 @@ static DDS_Security_boolean return_permissions_credential_token(
const DDS_Security_PermissionsCredentialToken *permissions_credential_token,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_credential_token);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->return_permissions_credential_token(impl->instance, permissions_credential_token, ex);
default:
return true;
}
}
static DDS_Security_boolean get_participant_sec_attributes(
@ -362,25 +564,35 @@ static DDS_Security_boolean get_participant_sec_attributes(
DDS_Security_ParticipantSecurityAttributes *attributes,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(attributes);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->get_participant_sec_attributes(impl->instance, permissions_handle, attributes, ex);
default:
return true;
}
}
static DDS_Security_boolean get_topic_sec_attributes( dds_security_access_control *instance,
static DDS_Security_boolean get_topic_sec_attributes(
dds_security_access_control *instance,
const DDS_Security_PermissionsHandle permissions_handle,
const char *topic_name,
DDS_Security_TopicSecurityAttributes *attributes,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(topic_name);
DDSRT_UNUSED_ARG(attributes);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->get_topic_sec_attributes(impl->instance, permissions_handle, topic_name, attributes, ex);
default:
return true;
}
}
static DDS_Security_boolean get_datawriter_sec_attributes(
@ -392,14 +604,16 @@ static DDS_Security_boolean get_datawriter_sec_attributes(
DDS_Security_EndpointSecurityAttributes *attributes,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(topic_name);
DDSRT_UNUSED_ARG(partition);
DDSRT_UNUSED_ARG(data_tag);
DDSRT_UNUSED_ARG(attributes);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->get_datawriter_sec_attributes(impl->instance, permissions_handle, topic_name, partition, data_tag, attributes, ex);
default:
return true;
}
}
static DDS_Security_boolean get_datareader_sec_attributes(
@ -411,14 +625,16 @@ static DDS_Security_boolean get_datareader_sec_attributes(
DDS_Security_EndpointSecurityAttributes *attributes,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(topic_name);
DDSRT_UNUSED_ARG(partition);
DDSRT_UNUSED_ARG(data_tag);
DDSRT_UNUSED_ARG(attributes);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->get_datareader_sec_attributes(impl->instance, permissions_handle, topic_name, partition, data_tag, attributes, ex);
default:
return true;
}
}
static DDS_Security_boolean return_participant_sec_attributes(
@ -426,10 +642,16 @@ static DDS_Security_boolean return_participant_sec_attributes(
const DDS_Security_ParticipantSecurityAttributes *attributes,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(attributes);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->return_participant_sec_attributes(impl->instance, attributes, ex);
default:
return true;
}
}
static DDS_Security_boolean return_topic_sec_attributes(
@ -437,10 +659,16 @@ static DDS_Security_boolean return_topic_sec_attributes(
const DDS_Security_TopicSecurityAttributes *attributes,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(attributes);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->return_topic_sec_attributes(impl->instance, attributes, ex);
default:
return true;
}
}
static DDS_Security_boolean return_datawriter_sec_attributes(
@ -448,10 +676,16 @@ static DDS_Security_boolean return_datawriter_sec_attributes(
const DDS_Security_EndpointSecurityAttributes *attributes,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(attributes);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->return_datawriter_sec_attributes(impl->instance, attributes, ex);
default:
return true;
}
}
static DDS_Security_boolean return_datareader_sec_attributes(
@ -459,10 +693,16 @@ static DDS_Security_boolean return_datareader_sec_attributes(
const DDS_Security_EndpointSecurityAttributes *attributes,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(attributes);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->return_datareader_sec_attributes(impl->instance, attributes, ex);
default:
return true;
}
}
static DDS_Security_boolean return_permissions_handle(
@ -470,17 +710,29 @@ static DDS_Security_boolean return_permissions_handle(
const DDS_Security_PermissionsHandle permissions_handle,
DDS_Security_SecurityException *ex)
{
DDSRT_UNUSED_ARG(permissions_handle);
DDSRT_UNUSED_ARG(ex);
DDSRT_UNUSED_ARG(instance);
return true;
struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance;
switch (impl->mode)
{
case PLUGIN_MODE_WRAPPED:
case PLUGIN_MODE_NOT_ALLOWED:
return impl->instance->return_permissions_handle(impl->instance, permissions_handle, ex);
default:
return true;
}
}
static struct dds_security_access_control_impl * init_test_access_control_common()
static struct dds_security_access_control_impl * init_test_access_control_common(const char *argument, bool wrapped, struct ddsi_domaingv *gv)
{
struct dds_security_access_control_impl *impl = ddsrt_malloc(sizeof(*impl));
memset(impl, 0, sizeof(*impl));
if (wrapped)
{
if (init_access_control(argument, (void **)&impl->instance, gv) != DDS_SECURITY_SUCCESS)
return NULL;
}
impl->base.validate_local_permissions = &validate_local_permissions;
impl->base.validate_remote_permissions = &validate_remote_permissions;
impl->base.check_create_participant = &check_create_participant;
@ -514,40 +766,90 @@ static struct dds_security_access_control_impl * init_test_access_control_common
return impl;
}
int32_t init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv)
static int finalize_test_access_control_common(struct dds_security_access_control_impl * impl, bool wrapped)
{
int32_t ret;
if (wrapped && (ret = finalize_access_control(impl->instance)) != DDS_SECURITY_SUCCESS)
return ret;
ddsrt_free(impl);
return DDS_SECURITY_SUCCESS;
}
int init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv)
{
DDSRT_UNUSED_ARG(argument);
DDSRT_UNUSED_ARG(context);
DDSRT_UNUSED_ARG(gv);
struct dds_security_access_control_impl *impl = init_test_access_control_common();
struct dds_security_access_control_impl *impl = init_test_access_control_common(argument, false, gv);
impl->mode = PLUGIN_MODE_ALL_OK;
*context = impl;
return 0;
}
int32_t finalize_test_access_control_all_ok(void *context)
int finalize_test_access_control_all_ok(void *context)
{
assert(((struct dds_security_access_control_impl *)context)->mode == PLUGIN_MODE_ALL_OK);
ddsrt_free(context);
return 0;
struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context;
assert(impl->mode == PLUGIN_MODE_ALL_OK);
return finalize_test_access_control_common(impl, false);
}
int32_t init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv)
int init_test_access_control_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv)
{
struct dds_security_access_control_impl *impl = init_test_access_control_common(argument, true, gv);
if (!impl)
return DDS_SECURITY_FAILED;
impl->mode = PLUGIN_MODE_WRAPPED;
*context = impl;
return DDS_SECURITY_SUCCESS;
}
int finalize_test_access_control_wrapped(void *context)
{
struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context;
assert(impl->mode == PLUGIN_MODE_WRAPPED);
return finalize_test_access_control_common(impl, true);
}
int init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv)
{
DDSRT_UNUSED_ARG(argument);
DDSRT_UNUSED_ARG(context);
DDSRT_UNUSED_ARG(gv);
struct dds_security_access_control_impl *impl = init_test_access_control_common();
struct dds_security_access_control_impl *impl = init_test_access_control_common(argument, false, gv);
impl->base.check_create_datareader = NULL;
impl->mode = PLUGIN_MODE_MISSING_FUNC;
*context = impl;
return 0;
}
int32_t finalize_test_access_control_missing_func(void *context)
int finalize_test_access_control_missing_func(void *context)
{
assert(((struct dds_security_access_control_impl *)context)->mode == PLUGIN_MODE_MISSING_FUNC);
ddsrt_free(context);
return 0;
struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context;
assert(impl->mode == PLUGIN_MODE_MISSING_FUNC);
return finalize_test_access_control_common(impl, false);
}
#define INIT_NOT_ALLOWED(name_, mask_) \
int init_test_access_control_##name_ (const char *argument, void **context, struct ddsi_domaingv *gv) \
{ \
DDSRT_UNUSED_ARG(context); \
struct dds_security_access_control_impl *impl = init_test_access_control_common(argument, true, gv); \
impl->mode = PLUGIN_MODE_NOT_ALLOWED; \
impl->not_allowed_mask = mask_; \
*context = impl; \
return 0; \
}
INIT_NOT_ALLOWED(local_participant_not_allowed, NOT_ALLOWED_LOCAL_PP)
INIT_NOT_ALLOWED(local_topic_not_allowed, NOT_ALLOWED_LOCAL_TOPIC)
INIT_NOT_ALLOWED(local_publishing_not_allowed, NOT_ALLOWED_LOCAL_PUB)
INIT_NOT_ALLOWED(local_subscribing_not_allowed, NOT_ALLOWED_LOCAL_SUB)
INIT_NOT_ALLOWED(remote_permissions_invalidate, NOT_ALLOWED_REMOTE_PERM)
INIT_NOT_ALLOWED(remote_participant_not_allowed, NOT_ALLOWED_REMOTE_PP)
INIT_NOT_ALLOWED(remote_topic_not_allowed, NOT_ALLOWED_REMOTE_TOPIC)
INIT_NOT_ALLOWED(remote_writer_not_allowed, NOT_ALLOWED_REMOTE_WRITER)
INIT_NOT_ALLOWED(remote_reader_not_allowed, NOT_ALLOWED_REMOTE_READER)
INIT_NOT_ALLOWED(remote_reader_relay_only, NOT_ALLOWED_REMOTE_READER_RELAY_ONLY)
int finalize_test_access_control_not_allowed(void *context)
{
struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context;
assert(impl->mode == PLUGIN_MODE_NOT_ALLOWED);
return finalize_test_access_control_common(impl, true);
}

View file

@ -16,12 +16,36 @@
#include "dds/security/dds_security_api.h"
#include "dds/security/access_control_wrapper_export.h"
/* Topic name prefix expected by this wrapper when running in not-allowed
mode. This prefix is used to exclude built-in topics from being disallowed. */
#define AC_WRAPPER_TOPIC_PREFIX "ddssec_access_control_"
/* Init in all-ok mode: all functions return success without calling the actual plugin */
SECURITY_EXPORT int32_t init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int32_t finalize_test_access_control_all_ok(void *context);
SECURITY_EXPORT int init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int finalize_test_access_control_all_ok(void *context);
/* Init in missing function mode: one of the function pointers is null */
SECURITY_EXPORT int32_t init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int32_t finalize_test_access_control_missing_func(void *context);
SECURITY_EXPORT int init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int finalize_test_access_control_missing_func(void *context);
SECURITY_EXPORT int init_test_access_control_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int finalize_test_access_control_wrapped(void *context);
/* Init functions for not-allowed modes */
#define INIT_NOT_ALLOWED_DECL(name_) \
SECURITY_EXPORT int init_test_access_control_##name_ (const char *argument, void **context, struct ddsi_domaingv *gv);
INIT_NOT_ALLOWED_DECL(local_participant_not_allowed)
INIT_NOT_ALLOWED_DECL(local_topic_not_allowed)
INIT_NOT_ALLOWED_DECL(local_publishing_not_allowed)
INIT_NOT_ALLOWED_DECL(local_subscribing_not_allowed)
INIT_NOT_ALLOWED_DECL(remote_permissions_invalidate)
INIT_NOT_ALLOWED_DECL(remote_participant_not_allowed)
INIT_NOT_ALLOWED_DECL(remote_topic_not_allowed)
INIT_NOT_ALLOWED_DECL(remote_writer_not_allowed)
INIT_NOT_ALLOWED_DECL(remote_reader_not_allowed)
INIT_NOT_ALLOWED_DECL(remote_reader_relay_only)
SECURITY_EXPORT int finalize_test_access_control_not_allowed(void *context);
#endif /* SECURITY_CORE_TEST_ACCESS_CONTROL_WRAPPER_H_ */

View file

@ -22,8 +22,8 @@
#include "test_identity.h"
#include "plugin_wrapper_msg_q.h"
int32_t init_authentication(const char *argument, void **context, struct ddsi_domaingv *gv);
int32_t finalize_authentication(void *context);
int init_authentication(const char *argument, void **context, struct ddsi_domaingv *gv);
int finalize_authentication(void *context);
enum auth_plugin_mode {
PLUGIN_MODE_ALL_OK,
@ -482,7 +482,7 @@ static struct dds_security_authentication_impl * init_test_authentication_common
return impl;
}
int32_t init_test_authentication_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv)
int init_test_authentication_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv)
{
DDSRT_UNUSED_ARG(argument);
DDSRT_UNUSED_ARG(context);
@ -493,14 +493,14 @@ int32_t init_test_authentication_all_ok(const char *argument, void **context, st
return 0;
}
int32_t finalize_test_authentication_all_ok(void *context)
int finalize_test_authentication_all_ok(void *context)
{
assert(((struct dds_security_authentication_impl *)context)->mode == PLUGIN_MODE_ALL_OK);
ddsrt_free(context);
return 0;
}
int32_t init_test_authentication_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv)
int init_test_authentication_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv)
{
DDSRT_UNUSED_ARG(argument);
DDSRT_UNUSED_ARG(context);
@ -512,14 +512,14 @@ int32_t init_test_authentication_missing_func(const char *argument, void **conte
return 0;
}
int32_t finalize_test_authentication_missing_func(void *context)
int finalize_test_authentication_missing_func(void *context)
{
assert(((struct dds_security_authentication_impl *)context)->mode == PLUGIN_MODE_MISSING_FUNC);
ddsrt_free(context);
return 0;
}
int32_t init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv)
int init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv)
{
DDSRT_UNUSED_ARG(argument);
DDSRT_UNUSED_ARG(context);
@ -527,7 +527,7 @@ int32_t init_test_authentication_init_error(const char *argument, void **context
return 1;
}
int32_t finalize_test_authentication_init_error(void *context)
int finalize_test_authentication_init_error(void *context)
{
DDSRT_UNUSED_ARG(context);
return 0;
@ -537,9 +537,9 @@ int32_t finalize_test_authentication_init_error(void *context)
* Init and fini functions for using wrapped mode for the authentication plugin.
* These functions assumes that there are no concurrent calls, as the static
* variables used here are not protected by a lock. */
int32_t init_test_authentication_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv)
int init_test_authentication_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv)
{
int32_t ret;
int ret;
struct dds_security_authentication_impl *impl = init_test_authentication_common();
impl->mode = PLUGIN_MODE_WRAPPED;
@ -553,9 +553,9 @@ int32_t init_test_authentication_wrapped(const char *argument, void **context, s
return ret;
}
int32_t finalize_test_authentication_wrapped(void *context)
int finalize_test_authentication_wrapped(void *context)
{
int32_t ret;
int ret;
struct dds_security_authentication_impl *impl = context;
assert(impl->mode == PLUGIN_MODE_WRAPPED);
deinit_message_queue(&impl->msg_queue);

View file

@ -18,20 +18,20 @@
#include "plugin_wrapper_msg_q.h"
/* Init in wrapper mode */
SECURITY_EXPORT int32_t init_test_authentication_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int32_t finalize_test_authentication_wrapped(void *context);
SECURITY_EXPORT int init_test_authentication_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int finalize_test_authentication_wrapped(void *context);
/* Init in all-ok mode: all functions return success without calling the actual plugin */
SECURITY_EXPORT int32_t init_test_authentication_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int32_t finalize_test_authentication_all_ok(void *context);
SECURITY_EXPORT int init_test_authentication_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int finalize_test_authentication_all_ok(void *context);
/* Init in missing function mode: one of the function pointers is null */
SECURITY_EXPORT int32_t init_test_authentication_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int32_t finalize_test_authentication_missing_func(void *context);
SECURITY_EXPORT int init_test_authentication_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int finalize_test_authentication_missing_func(void *context);
/* Init function fails */
SECURITY_EXPORT int32_t init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int32_t finalize_test_authentication_init_error(void *context);
SECURITY_EXPORT int init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int finalize_test_authentication_init_error(void *context);
SECURITY_EXPORT struct message * test_authentication_plugin_take_msg(dds_domainid_t domain_id, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout);
SECURITY_EXPORT void test_authentication_plugin_release_msg(struct message *msg);

View file

@ -22,8 +22,8 @@
#include "dds/security/core/dds_security_utils.h"
#include "cryptography_wrapper.h"
int32_t init_crypto(const char *argument, void **context, struct ddsi_domaingv *gv);
int32_t finalize_crypto(void *context);
int init_crypto(const char *argument, void **context, struct ddsi_domaingv *gv);
int finalize_crypto(void *context);
enum crypto_plugin_mode {
PLUGIN_MODE_ALL_OK,
@ -754,16 +754,16 @@ static struct dds_security_cryptography_impl * init_test_cryptography_common(con
return impl;
}
static int32_t finalize_test_cryptography_common(struct dds_security_cryptography_impl * impl, bool wrapped)
static int finalize_test_cryptography_common(struct dds_security_cryptography_impl * impl, bool wrapped)
{
int32_t ret;
int ret;
if (wrapped && (ret = finalize_crypto(impl->instance)) != DDS_SECURITY_SUCCESS)
return ret;
ddsrt_free(impl);
return DDS_SECURITY_SUCCESS;
}
int32_t init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv)
int init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv)
{
struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, false, gv);
if (!impl)
@ -773,14 +773,14 @@ int32_t init_test_cryptography_all_ok(const char *argument, void **context, stru
return DDS_SECURITY_SUCCESS;
}
int32_t finalize_test_cryptography_all_ok(void *context)
int finalize_test_cryptography_all_ok(void *context)
{
struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context;
assert(impl->mode == PLUGIN_MODE_ALL_OK);
return finalize_test_cryptography_common(impl, false);
}
int32_t init_test_cryptography_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv)
int init_test_cryptography_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv)
{
struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, false, gv);
if (!impl)
@ -791,14 +791,14 @@ int32_t init_test_cryptography_missing_func(const char *argument, void **context
return DDS_SECURITY_SUCCESS;
}
int32_t finalize_test_cryptography_missing_func(void *context)
int finalize_test_cryptography_missing_func(void *context)
{
struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context;
assert(impl->mode == PLUGIN_MODE_MISSING_FUNC);
return finalize_test_cryptography_common(impl, false);
}
int32_t init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv)
int init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv)
{
struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, true, gv);
if (!impl)
@ -808,7 +808,7 @@ int32_t init_test_cryptography_wrapped(const char *argument, void **context, str
return DDS_SECURITY_SUCCESS;
}
int32_t finalize_test_cryptography_wrapped(void *context)
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);

View file

@ -35,15 +35,15 @@ SECURITY_EXPORT void set_disc_protection_kinds(
SECURITY_EXPORT void set_entity_data_secret(struct dds_security_cryptography_impl * impl, const char * pp_secret, const char * groupdata_secret, const char * ep_secret);
/* Init in all-ok mode: all functions return success without calling the actual plugin */
SECURITY_EXPORT int32_t init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int32_t finalize_test_cryptography_all_ok(void *context);
SECURITY_EXPORT int init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int finalize_test_cryptography_all_ok(void *context);
/* Init in missing function mode: one of the function pointers is null */
SECURITY_EXPORT int32_t init_test_cryptography_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int32_t finalize_test_cryptography_missing_func(void *context);
SECURITY_EXPORT int init_test_cryptography_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int finalize_test_cryptography_missing_func(void *context);
/* Init in wrapper mode */
SECURITY_EXPORT int32_t init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int32_t finalize_test_cryptography_wrapped(void *context);
SECURITY_EXPORT int init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv);
SECURITY_EXPORT int finalize_test_cryptography_wrapped(void *context);
#endif /* SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ */

View file

@ -50,8 +50,8 @@ static const char *governance_xml =
" <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:-false}</enable_read_access_control>"
" <enable_write_access_control>${ENABLE_WRITE_AC:-false}</enable_write_access_control>"
" <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>"
@ -68,7 +68,7 @@ static const char *permissions_xml_grant =
" <subject_name>${SUBJECT_NAME}</subject_name>"
" <validity><not_before>${NOT_BEFORE:-2015-09-15T01:00:00}</not_before><not_after>${NOT_AFTER:-2115-09-15T01:00:00}</not_after></validity>"
" <allow_rule>"
" <domains><id_range><min>0</min><max>230</max></id_range></domains>"
" <domains>${DOMAIN_ID:+<id>}${DOMAIN_ID:-<id_range><min>0</min><max>230</max></id_range>}${DOMAIN_ID:+</id>}</domains>"
" <publish>"
" <topics>${PUB_TOPICS:-<topic>*</topic>}</topics>"
" <partitions><partition>*</partition></partitions>"
@ -239,7 +239,7 @@ static char * get_xml_datetime(dds_time_t t, char * buf, size_t len)
return buf;
}
char * get_permissions_grant(const char * name, const char * subject,
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)
{
char not_before_str[] = "0000-00-00T00:00:00Z";
@ -252,6 +252,7 @@ char * get_permissions_grant(const char * name, const char * subject,
{ "SUBJECT_NAME", subject, 1 },
{ "NOT_BEFORE", not_before_str, 1 },
{ "NOT_AFTER", not_after_str, 1 },
{ "DOMAIN_ID", domain_id, 3 },
{ "PUB_TOPICS", pub_topics, 1 },
{ "SUB_TOPICS", sub_topics, 1 },
{ "DEFAULT_POLICY", default_policy, 1 },

View file

@ -27,7 +27,7 @@ int32_t expand_lookup_unmatched (const struct kvp * lookup_table);
char * get_governance_config (struct kvp *config_vars, bool add_prefix);
char * get_permissions_topic(const char * name);
char * get_permissions_grant(const char * name, const char * subject,
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);
char * get_permissions_config(char * grants[], size_t ngrants, bool add_prefix);

View file

@ -294,10 +294,11 @@ void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_c
CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK);
while (true)
{
ret = dds_waitset_wait (ws, &triggered, 1, DDS_SECS(5));
CU_ASSERT_FATAL (ret >= 1);
CU_ASSERT_EQUAL_FATAL (wr, (dds_entity_t)(intptr_t) triggered);
ret = dds_get_publication_matched_status(wr, &pub_matched);
ret = dds_waitset_wait (ws, &triggered, 1, DDS_SECS(2));
CU_ASSERT_EQUAL_FATAL (exp_count > 0, ret >= 1);
if (exp_count > 0)
CU_ASSERT_EQUAL_FATAL (wr, (dds_entity_t)(intptr_t) triggered);
ret = dds_get_publication_matched_status (wr, &pub_matched);
CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK);
if (pub_matched.total_count >= exp_count)
break;
@ -306,6 +307,30 @@ void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_c
CU_ASSERT_EQUAL_FATAL (pub_matched.total_count, exp_count);
}
void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_count)
{
dds_attach_t triggered;
dds_entity_t ws = dds_create_waitset (pp_rd);
CU_ASSERT_FATAL (ws > 0);
dds_subscription_matched_status_t sub_matched;
dds_return_t ret = dds_waitset_attach (ws, rd, rd);
CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK);
while (true)
{
ret = dds_waitset_wait (ws, &triggered, 1, DDS_SECS(2));
CU_ASSERT_EQUAL_FATAL (exp_count > 0, ret >= 1);
if (exp_count > 0)
CU_ASSERT_EQUAL_FATAL (rd, (dds_entity_t)(intptr_t) triggered);
ret = dds_get_subscription_matched_status (rd, &sub_matched);
CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK);
if (sub_matched.total_count >= exp_count)
break;
};
dds_delete (ws);
CU_ASSERT_EQUAL_FATAL (sub_matched.total_count, exp_count);
}
char *create_topic_name (const char *prefix, uint32_t nr, char *name, size_t size)
{
ddsrt_pid_t pid = ddsrt_getpid ();
@ -328,10 +353,12 @@ bool reader_wait_for_data (dds_entity_t pp, dds_entity_t rd, dds_duration_t dur)
return ret > 0;
}
void rd_wr_init(
void rd_wr_init_fail(
dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr,
dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd,
const char * topic_name)
const char * topic_name,
bool exp_pubtp_fail, bool exp_wr_fail,
bool exp_subtp_fail, bool exp_rd_fail)
{
dds_qos_t * qos = dds_create_qos ();
CU_ASSERT_FATAL (qos != NULL);
@ -344,19 +371,37 @@ void rd_wr_init(
*sub = dds_create_subscriber (pp_rd, NULL, NULL);
CU_ASSERT_FATAL (*sub > 0);
*pub_tp = dds_create_topic (pp_wr, &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL);
CU_ASSERT_FATAL (*pub_tp > 0);
CU_ASSERT_EQUAL_FATAL (exp_pubtp_fail, *pub_tp <= 0);
*sub_tp = dds_create_topic (pp_rd, &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL);
CU_ASSERT_FATAL (*sub_tp > 0);
*wr = dds_create_writer (*pub, *pub_tp, qos, NULL);
CU_ASSERT_FATAL (*wr > 0);
dds_set_status_mask (*wr, DDS_PUBLICATION_MATCHED_STATUS);
*rd = dds_create_reader (*sub, *sub_tp, qos, NULL);
CU_ASSERT_FATAL (*rd > 0);
dds_set_status_mask (*rd, DDS_DATA_AVAILABLE_STATUS);
sync_writer_to_readers(pp_wr, *wr, 1);
CU_ASSERT_EQUAL_FATAL (exp_subtp_fail, *sub_tp <= 0);
if (!exp_pubtp_fail)
{
*wr = dds_create_writer (*pub, *pub_tp, qos, NULL);
CU_ASSERT_EQUAL_FATAL (exp_wr_fail, *wr <= 0);
if (exp_wr_fail)
goto fail;
dds_set_status_mask (*wr, DDS_PUBLICATION_MATCHED_STATUS);
}
if (!exp_subtp_fail)
{
*rd = dds_create_reader (*sub, *sub_tp, qos, NULL);
CU_ASSERT_EQUAL_FATAL (exp_rd_fail, *rd <= 0);
if (exp_rd_fail)
goto fail;
dds_set_status_mask (*rd, DDS_SUBSCRIPTION_MATCHED_STATUS);
}
fail:
dds_delete_qos (qos);
}
void rd_wr_init(
dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr,
dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd,
const char * topic_name)
{
rd_wr_init_fail (pp_wr, pub, pub_tp, wr, pp_rd, sub, sub_tp, rd, topic_name, false, false, false, false);
}
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)
{
SecurityCoreTests_Type1 sample = { 1, 1 };
@ -367,9 +412,10 @@ void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_du
dds_time_t tend = dds_time () + dur;
bool write_fail = false, read_fail = false;
dds_set_status_mask (rd, DDS_DATA_AVAILABLE_STATUS);
do
{
print_test_msg("write\n");
print_test_msg ("write\n");
if (dds_write (wr, &sample) != DDS_RETCODE_OK)
write_fail = true;
@ -399,7 +445,7 @@ void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_du
break;
dds_sleepfor (DDS_MSECS (100));
}
while (dds_time() < tend);
while (dds_time () < tend);
CU_ASSERT_EQUAL_FATAL (write_fail, exp_write_fail);
CU_ASSERT_EQUAL_FATAL (read_fail, exp_read_fail);
}

View file

@ -56,11 +56,18 @@ void validate_handshake_nofail (dds_domainid_t domain_id);
void handshake_list_fini(struct Handshake *hs_list, int nhs);
char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size);
void sync_writer_to_readers(dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count);
void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_count);
bool reader_wait_for_data(dds_entity_t pp, dds_entity_t rd, dds_duration_t dur);
void rd_wr_init(
dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr,
dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd,
const char *topic_name);
const char * topic_name);
void rd_wr_init_fail(
dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr,
dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd,
const char * topic_name,
bool exp_pubtp_fail, bool exp_wr_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);
#endif /* SECURITY_CORE_TEST_UTILS_H_ */