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

@ -30,6 +30,7 @@
#include "dds__builtin.h"
#include "dds/ddsi/ddsi_sertopic.h"
#include "dds/ddsi/ddsi_entity_index.h"
#include "dds/ddsi/ddsi_security_omg.h"
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_reader)
@ -430,6 +431,7 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
/* Merge qos from topic and subscriber, dds_copy_qos only fails when it is passed a null
argument, but that isn't the case here */
struct ddsi_domaingv *gv = &sub->m_entity.m_domain->gv;
rqos = dds_create_qos ();
if (qos)
ddsi_xqos_mergein_missing (rqos, qos, DDS_READER_QOS_MASK);
@ -437,25 +439,43 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
ddsi_xqos_mergein_missing (rqos, sub->m_entity.m_qos, ~(uint64_t)0);
if (tp->m_ktopic->qos)
ddsi_xqos_mergein_missing (rqos, tp->m_ktopic->qos, ~(uint64_t)0);
ddsi_xqos_mergein_missing (rqos, &sub->m_entity.m_domain->gv.default_xqos_rd, ~(uint64_t)0);
ddsi_xqos_mergein_missing (rqos, &gv->default_xqos_rd, ~(uint64_t)0);
if ((rc = ddsi_xqos_valid (&sub->m_entity.m_domain->gv.logconfig, rqos)) < 0 ||
(rc = validate_reader_qos(rqos)) != DDS_RETCODE_OK)
{
dds_delete_qos (rqos);
if ((rc = ddsi_xqos_valid (&gv->logconfig, rqos)) < 0 || (rc = validate_reader_qos(rqos)) != DDS_RETCODE_OK)
goto err_bad_qos;
}
/* Additional checks required for built-in topics: we don't want to
run into a resource limit on a built-in topic, it is a needless
complication */
if (pseudo_topic && !dds__validate_builtin_reader_qos (tp->m_entity.m_domain, pseudo_topic, rqos))
{
dds_delete_qos (rqos);
rc = DDS_RETCODE_INCONSISTENT_POLICY;
goto err_bad_qos;
}
thread_state_awake (lookup_thread_state (), gv);
const struct ddsi_guid * ppguid = dds_entity_participant_guid (&sub->m_entity);
struct participant * pp = entidx_lookup_participant_guid (gv->entity_index, ppguid);
if (pp == NULL)
{
GVLOGDISC ("new_reader - participant "PGUIDFMT" not found\n", PGUID (*ppguid));
rc = DDS_RETCODE_BAD_PARAMETER;
goto err_pp_not_found;
}
#ifdef DDSI_INCLUDE_SECURITY
/* Check if DDS Security is enabled */
if (q_omg_participant_is_secure (pp))
{
/* ask to access control security plugin for create reader permissions */
if (!q_omg_security_check_create_reader (pp, gv->config.domainId, tp->m_stopic->name, rqos))
{
rc = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
goto err_not_allowed;
}
}
#endif
/* Create reader and associated read cache (if not provided by caller) */
struct dds_reader * const rd = dds_alloc (sizeof (*rd));
const dds_entity_t reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, false, rqos, listener, DDS_READER_STATUS_MASK);
@ -474,8 +494,7 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
it; and then invoke those listeners that are in the pending set */
dds_entity_init_complete (&rd->m_entity);
thread_state_awake (lookup_thread_state (), &sub->m_entity.m_domain->gv);
rc = new_reader (&rd->m_rd, &rd->m_entity.m_domain->gv, &rd->m_entity.m_guid, NULL, dds_entity_participant_guid (&sub->m_entity), tp->m_stopic, rqos, &rd->m_rhc->common.rhc, dds_reader_status_cb, rd);
rc = new_reader (&rd->m_rd, &rd->m_entity.m_guid, NULL, pp, tp->m_stopic, rqos, &rd->m_rhc->common.rhc, dds_reader_status_cb, rd);
assert (rc == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */
thread_state_asleep (lookup_thread_state ());
@ -487,7 +506,13 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
dds_subscriber_unlock (sub);
return reader;
#ifdef DDSI_INCLUDE_SECURITY
err_not_allowed:
#endif
err_pp_not_found:
thread_state_asleep (lookup_thread_state ());
err_bad_qos:
dds_delete_qos (rqos);
dds_topic_allow_set_qos (tp);
err_pp_mismatch:
dds_topic_unpin (tp);

View file

@ -20,6 +20,7 @@
#include "dds/ddsi/q_thread.h"
#include "dds/ddsi/q_xmsg.h"
#include "dds/ddsi/ddsi_entity_index.h"
#include "dds/ddsi/ddsi_security_omg.h"
#include "dds__writer.h"
#include "dds__listener.h"
#include "dds__init.h"
@ -312,6 +313,7 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
dds_topic_defer_set_qos (tp);
/* Merge Topic & Publisher qos */
struct ddsi_domaingv *gv = &pub->m_entity.m_domain->gv;
wqos = dds_create_qos ();
if (qos)
ddsi_xqos_mergein_missing (wqos, qos, DDS_WRITER_QOS_MASK);
@ -319,29 +321,47 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
ddsi_xqos_mergein_missing (wqos, pub->m_entity.m_qos, ~(uint64_t)0);
if (tp->m_ktopic->qos)
ddsi_xqos_mergein_missing (wqos, tp->m_ktopic->qos, ~(uint64_t)0);
ddsi_xqos_mergein_missing (wqos, &pub->m_entity.m_domain->gv.default_xqos_wr, ~(uint64_t)0);
ddsi_xqos_mergein_missing (wqos, &gv->default_xqos_wr, ~(uint64_t)0);
if ((rc = ddsi_xqos_valid (&pub->m_entity.m_domain->gv.logconfig, wqos)) < 0 ||
(rc = validate_writer_qos(wqos)) != DDS_RETCODE_OK)
{
dds_delete_qos(wqos);
if ((rc = ddsi_xqos_valid (&gv->logconfig, wqos)) < 0 || (rc = validate_writer_qos(wqos)) != DDS_RETCODE_OK)
goto err_bad_qos;
thread_state_awake (lookup_thread_state (), gv);
const struct ddsi_guid *ppguid = dds_entity_participant_guid (&pub->m_entity);
struct participant *pp = entidx_lookup_participant_guid (gv->entity_index, ppguid);
if (pp == NULL)
{
GVLOGDISC ("new_writer - participant "PGUIDFMT" not found\n", PGUID (*ppguid));
rc = DDS_RETCODE_BAD_PARAMETER;
goto err_pp_not_found;
}
#ifdef DDSI_INCLUDE_SECURITY
/* Check if DDS Security is enabled */
if (q_omg_participant_is_secure (pp))
{
/* ask to access control security plugin for create writer permissions */
if (!q_omg_security_check_create_writer (pp, gv->config.domainId, tp->m_stopic->name, wqos))
{
rc = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
goto err_not_allowed;
}
}
#endif
/* Create writer */
ddsi_tran_conn_t conn = pub->m_entity.m_domain->gv.xmit_conn;
ddsi_tran_conn_t conn = gv->xmit_conn;
struct dds_writer * const wr = dds_alloc (sizeof (*wr));
const dds_entity_t writer = dds_entity_init (&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, false, wqos, listener, DDS_WRITER_STATUS_MASK);
wr->m_topic = tp;
dds_entity_add_ref_locked (&tp->m_entity);
wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), pub->m_entity.m_domain->gv.config.xpack_send_async);
wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), gv->config.xpack_send_async);
wrinfo = whc_make_wrinfo (wr, wqos);
wr->m_whc = whc_new (&pub->m_entity.m_domain->gv, wrinfo);
wr->m_whc = whc_new (gv, wrinfo);
whc_free_wrinfo (wrinfo);
wr->whc_batch = pub->m_entity.m_domain->gv.config.whc_batch;
wr->whc_batch = gv->config.whc_batch;
thread_state_awake (lookup_thread_state (), &pub->m_entity.m_domain->gv);
rc = new_writer (&wr->m_wr, &wr->m_entity.m_domain->gv, &wr->m_entity.m_guid, NULL, dds_entity_participant_guid (&pub->m_entity), tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr);
rc = new_writer (&wr->m_wr, &wr->m_entity.m_guid, NULL, pp, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr);
assert(rc == DDS_RETCODE_OK);
thread_state_asleep (lookup_thread_state ());
@ -355,7 +375,13 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
dds_publisher_unlock (pub);
return writer;
#ifdef DDSI_INCLUDE_SECURITY
err_not_allowed:
#endif
err_pp_not_found:
thread_state_asleep (lookup_thread_state ());
err_bad_qos:
dds_delete_qos(wqos);
dds_topic_allow_set_qos (tp);
err_pp_mismatch:
dds_topic_unpin (tp);