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:
		
							parent
							
								
									080514d45a
								
							
						
					
					
						commit
						19bc6f33cc
					
				
					 21 changed files with 1022 additions and 437 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue