Do not silently ignore security QoS settings
When built without support for DDS Security, any attempt to create a participant QoS settings in the security name space (those prefixed by "dds.sec.") must fail. Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
		
							parent
							
								
									4fe9cf290d
								
							
						
					
					
						commit
						d4e9300dad
					
				
					 6 changed files with 226 additions and 156 deletions
				
			
		| 
						 | 
				
			
			@ -141,3 +141,43 @@ CU_Test(ddsc_security_config, empty, .init = ddsrt_init, .fini = ddsrt_fini)
 | 
			
		|||
  CU_ASSERT_FATAL(found == 0x7);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CU_Test(ddsc_security_qos, empty, .init = ddsrt_init, .fini = ddsrt_fini)
 | 
			
		||||
{
 | 
			
		||||
  /* Expected traces when creating participant with some (not all) security QoS
 | 
			
		||||
     settings.  We need to test this one here to be sure that it also refuses to
 | 
			
		||||
     start when security is configured but the implementation doesn't include
 | 
			
		||||
     support for it. */
 | 
			
		||||
  const char *log_expected[] = {
 | 
			
		||||
#ifdef DDSI_INCLUDE_SECURITY
 | 
			
		||||
    "new_participant(*): using security settings from QoS*",
 | 
			
		||||
    "new_participant(*): required security property * missing*",
 | 
			
		||||
#endif
 | 
			
		||||
    NULL
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  /* Set up the trace sinks to detect the config parsing. */
 | 
			
		||||
  dds_set_log_mask (DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG);
 | 
			
		||||
  dds_set_log_sink (&logger, (void *) log_expected);
 | 
			
		||||
  dds_set_trace_sink (&logger, (void *) log_expected);
 | 
			
		||||
 | 
			
		||||
  /* Create participant with incomplete/nonsensical security configuration: this should always fail */
 | 
			
		||||
  found = 0;
 | 
			
		||||
  dds_qos_t *qos = dds_create_qos ();
 | 
			
		||||
  dds_qset_prop (qos, "dds.sec.nonsense", "");
 | 
			
		||||
  dds_entity_t domain = dds_create_domain (0, "<Tracing><Category>trace</Category>");
 | 
			
		||||
  CU_ASSERT_FATAL (domain > 0);
 | 
			
		||||
  dds_entity_t participant = dds_create_participant (0, qos, NULL);
 | 
			
		||||
  dds_delete_qos (qos);
 | 
			
		||||
  CU_ASSERT_FATAL (participant < 0);
 | 
			
		||||
  (void) dds_delete (domain);
 | 
			
		||||
  dds_set_log_sink (NULL, NULL);
 | 
			
		||||
  dds_set_trace_sink (NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  /* All traces should have been provided. */
 | 
			
		||||
#ifndef DDSI_INCLUDE_SECURITY
 | 
			
		||||
  CU_ASSERT_FATAL (found == 0x0);
 | 
			
		||||
#else
 | 
			
		||||
  CU_ASSERT_FATAL (found == 0x3);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -184,11 +184,12 @@ bool q_omg_proxy_participant_is_secure(const struct proxy_participant *proxypp);
 | 
			
		|||
 * @param[in] pp         The participant to check if alloweed by security.
 | 
			
		||||
 * #param[in] domain_id  The domain_id
 | 
			
		||||
 *
 | 
			
		||||
 * @returns bool
 | 
			
		||||
 * @retval true   Participant is allowed
 | 
			
		||||
 * @retval false  Participant is not allowed
 | 
			
		||||
 * @returns dds_return_t
 | 
			
		||||
 * @retval DDS_RETCODE_OK   Participant is allowed
 | 
			
		||||
 * @retval DDS_RETCODE_NOT_ALLOWED_BY_SECURITY
 | 
			
		||||
 *                          Participant is not allowed
 | 
			
		||||
 */
 | 
			
		||||
bool q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id);
 | 
			
		||||
dds_return_t q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id);
 | 
			
		||||
 | 
			
		||||
void q_omg_security_participant_set_initialized(struct participant *pp);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -322,7 +322,9 @@ DDS_EXPORT void ddsi_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, ui
 | 
			
		|||
DDS_EXPORT void ddsi_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos);
 | 
			
		||||
DDS_EXPORT size_t ddsi_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos);
 | 
			
		||||
DDS_EXPORT dds_qos_t *ddsi_xqos_dup (const dds_qos_t *src);
 | 
			
		||||
DDS_EXPORT bool ddsi_xqos_has_prop (const dds_qos_t *xqos, const char *pname, bool startswith, bool check_non_empty);
 | 
			
		||||
DDS_EXPORT bool ddsi_xqos_has_prop_prefix (const dds_qos_t *xqos, const char *nameprefix);
 | 
			
		||||
DDS_EXPORT bool ddsi_xqos_find_prop (const dds_qos_t *xqos, const char *name, const char **value);
 | 
			
		||||
 | 
			
		||||
#ifdef DDSI_INCLUDE_SECURITY
 | 
			
		||||
struct omg_security_configuration_type;
 | 
			
		||||
DDS_EXPORT void ddsi_xqos_mergein_security_config (dds_qos_t *xqos, const struct omg_security_configuration_type *cfg);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3179,16 +3179,30 @@ dds_qos_t * ddsi_xqos_dup (const dds_qos_t *src)
 | 
			
		|||
  return dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ddsi_xqos_has_prop (const dds_qos_t *xqos, const char *pname, bool startswith, bool check_non_empty)
 | 
			
		||||
bool ddsi_xqos_has_prop_prefix (const dds_qos_t *xqos, const char *nameprefix)
 | 
			
		||||
{
 | 
			
		||||
  if (!(xqos->present & QP_PROPERTY_LIST))
 | 
			
		||||
    return false;
 | 
			
		||||
  const size_t len = strlen (nameprefix);
 | 
			
		||||
  for (uint32_t i = 0; i < xqos->property.value.n; i++)
 | 
			
		||||
  {
 | 
			
		||||
    if (strncmp (xqos->property.value.props[i].name, nameprefix, len) == 0)
 | 
			
		||||
      return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  for (uint32_t i = 0; i < xqos->property.value.n; i++) {
 | 
			
		||||
    if (startswith && (strncmp(xqos->property.value.props[i].name, pname, strlen(pname)) == 0)) {
 | 
			
		||||
      return !check_non_empty || strlen(xqos->property.value.props[i].value) != 0;
 | 
			
		||||
    } else if (!startswith && (strcmp(xqos->property.value.props[i].name, pname) == 0)) {
 | 
			
		||||
      return !check_non_empty || strlen(xqos->property.value.props[i].value) != 0;
 | 
			
		||||
bool ddsi_xqos_find_prop (const dds_qos_t *xqos, const char *name, const char **value)
 | 
			
		||||
{
 | 
			
		||||
  if (!(xqos->present & QP_PROPERTY_LIST))
 | 
			
		||||
    return false;
 | 
			
		||||
  for (uint32_t i = 0; i < xqos->property.value.n; i++)
 | 
			
		||||
  {
 | 
			
		||||
    if (strcmp (xqos->property.value.props[i].name, name) == 0)
 | 
			
		||||
    {
 | 
			
		||||
      if (value)
 | 
			
		||||
        *value = xqos->property.value.props[i].value;
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -844,9 +844,9 @@ bool q_omg_participant_allow_unauthenticated(struct participant *pp)
 | 
			
		|||
  return ((pp->sec_attr != NULL) && pp->sec_attr->attr.allow_unauthenticated_participants);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id)
 | 
			
		||||
dds_return_t q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id)
 | 
			
		||||
{
 | 
			
		||||
  bool allowed = false;
 | 
			
		||||
  dds_return_t ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
 | 
			
		||||
  struct dds_security_context *sc = q_omg_security_get_secure_context(pp);
 | 
			
		||||
  DDS_Security_IdentityHandle identity_handle = DDS_SECURITY_HANDLE_NIL;
 | 
			
		||||
  DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT;
 | 
			
		||||
| 
						 | 
				
			
			@ -860,7 +860,7 @@ bool q_omg_security_check_create_participant(struct participant *pp, uint32_t do
 | 
			
		|||
  ddsi_guid_t adjusted_guid;
 | 
			
		||||
 | 
			
		||||
  if (!sc)
 | 
			
		||||
    return true;
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
 | 
			
		||||
  /* Validate local identity */
 | 
			
		||||
  ETRACE (pp, "validate_local_identity: candidate_guid: "PGUIDFMT" ", PGUID (pp->e.guid));
 | 
			
		||||
| 
						 | 
				
			
			@ -953,7 +953,7 @@ bool q_omg_security_check_create_participant(struct participant *pp, uint32_t do
 | 
			
		|||
 | 
			
		||||
  ETRACE (pp, "\n");
 | 
			
		||||
 | 
			
		||||
  allowed = true;
 | 
			
		||||
  ret = DDS_RETCODE_OK;
 | 
			
		||||
 | 
			
		||||
no_crypto:
 | 
			
		||||
no_sec_attr:
 | 
			
		||||
| 
						 | 
				
			
			@ -963,11 +963,11 @@ no_credentials:
 | 
			
		|||
  if (credential_token.class_id)
 | 
			
		||||
    (void)sc->access_control_context->return_permissions_credential_token(sc->access_control_context, &credential_token, NULL);
 | 
			
		||||
not_allowed:
 | 
			
		||||
  if (!allowed)
 | 
			
		||||
  if (ret != DDS_RETCODE_OK)
 | 
			
		||||
    participant_sec_attributes_free(sec_attr);
 | 
			
		||||
validation_failed:
 | 
			
		||||
  q_omg_shallow_free_security_qos(&par_qos);
 | 
			
		||||
  return allowed;
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void q_omg_security_participant_set_initialized(struct participant *pp)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -204,7 +204,6 @@ int is_builtin_endpoint (ddsi_entityid_t id, nn_vendorid_t vendorid)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DDSI_INCLUDE_SECURITY
 | 
			
		||||
 | 
			
		||||
static int is_builtin_volatile_endpoint (ddsi_entityid_t id)
 | 
			
		||||
{
 | 
			
		||||
  switch (id.u) {
 | 
			
		||||
| 
						 | 
				
			
			@ -217,13 +216,13 @@ static int is_builtin_volatile_endpoint (ddsi_entityid_t id)
 | 
			
		|||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
static int is_builtin_volatile_endpoint (ddsi_entityid_t id)
 | 
			
		||||
{
 | 
			
		||||
  DDSRT_UNUSED_ARG(id);
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool is_local_orphan_endpoint (const struct entity_common *e)
 | 
			
		||||
| 
						 | 
				
			
			@ -633,9 +632,63 @@ static void add_security_builtin_endpoints(struct participant *pp, ddsi_guid_t *
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void add_builtin_endpoints(struct participant *pp, ddsi_guid_t *subguid, const ddsi_guid_t *group_guid, struct ddsi_domaingv *gv, bool add_writers, bool add_readers)
 | 
			
		||||
{
 | 
			
		||||
  if (add_writers)
 | 
			
		||||
  {
 | 
			
		||||
    struct whc_writer_info *wrinfo = whc_make_wrinfo (NULL, &gv->builtin_endpoint_xqos_wr);
 | 
			
		||||
 | 
			
		||||
    /* SEDP writers: */
 | 
			
		||||
    subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER);
 | 
			
		||||
    new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER;
 | 
			
		||||
 | 
			
		||||
    subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER);
 | 
			
		||||
    new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER;
 | 
			
		||||
 | 
			
		||||
    /* PMD writer: */
 | 
			
		||||
    subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER);
 | 
			
		||||
    new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER;
 | 
			
		||||
 | 
			
		||||
    if (gv->config.do_topic_discovery)
 | 
			
		||||
    {
 | 
			
		||||
      subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER);
 | 
			
		||||
      new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL);
 | 
			
		||||
      pp->bes |= NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    whc_free_wrinfo (wrinfo);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* SPDP, SEDP, PMD readers: */
 | 
			
		||||
  if (add_readers)
 | 
			
		||||
  {
 | 
			
		||||
    subguid->entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER);
 | 
			
		||||
    new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->spdp_endpoint_xqos, NULL, NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR;
 | 
			
		||||
 | 
			
		||||
    subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER);
 | 
			
		||||
    new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR;
 | 
			
		||||
 | 
			
		||||
    subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER);
 | 
			
		||||
    new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_DETECTOR;
 | 
			
		||||
 | 
			
		||||
    subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER);
 | 
			
		||||
    new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#ifdef DDSI_INCLUDE_SECURITY
 | 
			
		||||
  if (q_omg_participant_is_secure (pp))
 | 
			
		||||
    add_security_builtin_endpoints (pp, subguid, group_guid, gv, add_writers, add_readers);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DDSI_INCLUDE_SECURITY
 | 
			
		||||
static void connect_participant_secure(struct ddsi_domaingv *gv, struct participant *pp)
 | 
			
		||||
{
 | 
			
		||||
  struct proxy_participant *proxypp;
 | 
			
		||||
| 
						 | 
				
			
			@ -749,6 +802,81 @@ static void participant_remove_wr_lease_locked (struct participant * pp, struct
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DDSI_INCLUDE_SECURITY
 | 
			
		||||
static dds_return_t check_and_load_security_config (struct ddsi_domaingv * const gv, const ddsi_guid_t *ppguid, dds_qos_t *qos)
 | 
			
		||||
{
 | 
			
		||||
  /* If some security properties (name starts with dds.sec. conform DDS Security spec 7.2.4.1)
 | 
			
		||||
     are present in the QoS, all must be and they will be used.  If none are, take the settings
 | 
			
		||||
     from the configuration if it has them.  When no security configuration exists anywhere,
 | 
			
		||||
     create an unsecured participant.
 | 
			
		||||
 | 
			
		||||
     This may modify "qos" */
 | 
			
		||||
  if (ddsi_xqos_has_prop_prefix (qos, "dds.sec."))
 | 
			
		||||
  {
 | 
			
		||||
    char const * const req[] = {
 | 
			
		||||
      DDS_SEC_PROP_AUTH_IDENTITY_CA,
 | 
			
		||||
      DDS_SEC_PROP_AUTH_PRIV_KEY,
 | 
			
		||||
      DDS_SEC_PROP_AUTH_IDENTITY_CERT,
 | 
			
		||||
      DDS_SEC_PROP_ACCESS_PERMISSIONS_CA,
 | 
			
		||||
      DDS_SEC_PROP_ACCESS_GOVERNANCE,
 | 
			
		||||
      DDS_SEC_PROP_ACCESS_PERMISSIONS,
 | 
			
		||||
 | 
			
		||||
      DDS_SEC_PROP_AUTH_LIBRARY_PATH,
 | 
			
		||||
      DDS_SEC_PROP_AUTH_LIBRARY_INIT,
 | 
			
		||||
      DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE,
 | 
			
		||||
      DDS_SEC_PROP_CRYPTO_LIBRARY_PATH,
 | 
			
		||||
      DDS_SEC_PROP_CRYPTO_LIBRARY_INIT,
 | 
			
		||||
      DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE,
 | 
			
		||||
      DDS_SEC_PROP_ACCESS_LIBRARY_PATH,
 | 
			
		||||
      DDS_SEC_PROP_ACCESS_LIBRARY_INIT,
 | 
			
		||||
      DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE
 | 
			
		||||
    };
 | 
			
		||||
    GVLOGDISC ("new_participant("PGUIDFMT"): using security settings from QoS\n", PGUID (*ppguid));
 | 
			
		||||
 | 
			
		||||
    /* check if all required security properties exist in qos; report all missing ones, not just the first */
 | 
			
		||||
    dds_return_t ret = DDS_RETCODE_OK;
 | 
			
		||||
    for (size_t i = 0; i < sizeof(req) / sizeof(req[0]); i++)
 | 
			
		||||
    {
 | 
			
		||||
      const char *value;
 | 
			
		||||
      if (!ddsi_xqos_find_prop (qos, req[i], &value) || strlen (value) == 0)
 | 
			
		||||
      {
 | 
			
		||||
        GVERROR ("new_participant("PGUIDFMT"): required security property %s missing in Property QoS\n", PGUID (*ppguid), req[i]);
 | 
			
		||||
        ret = DDS_RETCODE_PRECONDITION_NOT_MET;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (ret != DDS_RETCODE_OK)
 | 
			
		||||
      return ret;
 | 
			
		||||
  }
 | 
			
		||||
  else if (gv->config.omg_security_configuration)
 | 
			
		||||
  {
 | 
			
		||||
    /* For security, configuration can be provided through the configuration.  However, the specification
 | 
			
		||||
       (and the plugins) expect it to be in the QoS, so merge it in. */
 | 
			
		||||
    GVLOGDISC ("new_participant("PGUIDFMT"): using security settings from configuration\n", PGUID (*ppguid));
 | 
			
		||||
    ddsi_xqos_mergein_security_config (qos, &gv->config.omg_security_configuration->cfg);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    /* No security configuration */
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (q_omg_is_security_loaded (gv->security_context))
 | 
			
		||||
  {
 | 
			
		||||
    GVLOGDISC ("new_participant("PGUIDFMT"): security is already loaded for this domain\n", PGUID (*ppguid));
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
  }
 | 
			
		||||
  else if (q_omg_security_load (gv->security_context, qos) < 0)
 | 
			
		||||
  {
 | 
			
		||||
    GVERROR ("Could not load security\n");
 | 
			
		||||
    return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    return DDS_RETCODE_OK;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const ddsi_plist_t *plist)
 | 
			
		||||
{
 | 
			
		||||
  struct participant *pp;
 | 
			
		||||
| 
						 | 
				
			
			@ -828,77 +956,18 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv
 | 
			
		|||
 | 
			
		||||
#ifdef DDSI_INCLUDE_SECURITY
 | 
			
		||||
  pp->sec_attr = NULL;
 | 
			
		||||
  /*
 | 
			
		||||
   * if there there are security properties check them .
 | 
			
		||||
   * if there are no security properties, then merge from security configuration if there is
 | 
			
		||||
   */
 | 
			
		||||
  /* check for existing security properties (name starts with dds.sec. conform DDS Security spec 7.2.4.1)
 | 
			
		||||
   * and return if any is found */
 | 
			
		||||
  if ((ret = check_and_load_security_config (gv, ppguid, &pp->plist->qos)) != DDS_RETCODE_OK)
 | 
			
		||||
    goto not_allowed;
 | 
			
		||||
  if ((ret = q_omg_security_check_create_participant (pp, gv->config.domainId)) != DDS_RETCODE_OK)
 | 
			
		||||
    goto not_allowed;
 | 
			
		||||
  *ppguid = pp->e.guid;
 | 
			
		||||
#else
 | 
			
		||||
  if (ddsi_xqos_has_prop_prefix (&pp->plist->qos, "dds.sec."))
 | 
			
		||||
  {
 | 
			
		||||
    bool ready_to_load_security = false;
 | 
			
		||||
    if (ddsi_xqos_has_prop(&pp->plist->qos, "dds.sec.", true, false)) {
 | 
			
		||||
      char *req[] = {DDS_SEC_PROP_AUTH_IDENTITY_CA,
 | 
			
		||||
                     DDS_SEC_PROP_AUTH_PRIV_KEY,
 | 
			
		||||
                     DDS_SEC_PROP_AUTH_IDENTITY_CERT,
 | 
			
		||||
                     DDS_SEC_PROP_ACCESS_PERMISSIONS_CA,
 | 
			
		||||
                     DDS_SEC_PROP_ACCESS_GOVERNANCE,
 | 
			
		||||
                     DDS_SEC_PROP_ACCESS_PERMISSIONS,
 | 
			
		||||
 | 
			
		||||
                     DDS_SEC_PROP_AUTH_LIBRARY_PATH,
 | 
			
		||||
                     DDS_SEC_PROP_AUTH_LIBRARY_INIT,
 | 
			
		||||
                     DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE,
 | 
			
		||||
                     DDS_SEC_PROP_CRYPTO_LIBRARY_PATH,
 | 
			
		||||
                     DDS_SEC_PROP_CRYPTO_LIBRARY_INIT,
 | 
			
		||||
                     DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE,
 | 
			
		||||
                     DDS_SEC_PROP_ACCESS_LIBRARY_PATH,
 | 
			
		||||
                     DDS_SEC_PROP_ACCESS_LIBRARY_INIT,
 | 
			
		||||
                     DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE};
 | 
			
		||||
      GVLOGDISC ("new_participant("
 | 
			
		||||
                         PGUIDFMT
 | 
			
		||||
                         "): using security settings from QoS\n", PGUID(*ppguid));
 | 
			
		||||
 | 
			
		||||
      /* check if all required security properties exist in qos */
 | 
			
		||||
      for (size_t i = 0; i < sizeof(req) / sizeof(req[0]); i++) {
 | 
			
		||||
        if (!ddsi_xqos_has_prop(&pp->plist->qos, req[i], false, true)) {
 | 
			
		||||
          GVERROR ("new_participant("
 | 
			
		||||
                           PGUIDFMT
 | 
			
		||||
                           "): required security property %s missing in Property QoS\n", PGUID(*ppguid), req[i]);
 | 
			
		||||
          ret = DDS_RETCODE_PRECONDITION_NOT_MET;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (ret == DDS_RETCODE_OK) {
 | 
			
		||||
        ready_to_load_security = true;
 | 
			
		||||
      } else {
 | 
			
		||||
        goto new_pp_err_secprop;
 | 
			
		||||
      }
 | 
			
		||||
    } else if (gv->config.omg_security_configuration) {
 | 
			
		||||
      /* For security, configuration can be provided through the configuration.
 | 
			
		||||
       * However, the specification (and the plugins) expect it to be in the QoS. */
 | 
			
		||||
      GVLOGDISC ("new_participant("
 | 
			
		||||
                         PGUIDFMT
 | 
			
		||||
                         "): using security settings from configuration\n", PGUID(*ppguid));
 | 
			
		||||
      ddsi_xqos_mergein_security_config(&pp->plist->qos, &gv->config.omg_security_configuration->cfg);
 | 
			
		||||
      ready_to_load_security = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( q_omg_is_security_loaded( gv->security_context ) == false ){
 | 
			
		||||
      if (ready_to_load_security && q_omg_security_load(gv->security_context, &pp->plist->qos) < 0) {
 | 
			
		||||
        GVERROR("Could not load security\n");
 | 
			
		||||
        ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
 | 
			
		||||
        goto new_pp_err_secprop;
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      GVLOGDISC ("new_participant("
 | 
			
		||||
                               PGUIDFMT
 | 
			
		||||
                               "): security is already loaded for this domain\n", PGUID(*ppguid));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!q_omg_security_check_create_participant (pp, gv->config.domainId))
 | 
			
		||||
    {
 | 
			
		||||
      ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
 | 
			
		||||
      goto not_allowed;
 | 
			
		||||
    }
 | 
			
		||||
    *ppguid = pp->e.guid;
 | 
			
		||||
    /* disallow creating a participant with a security configuration if there is support for security
 | 
			
		||||
       has been left out */
 | 
			
		||||
    ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
 | 
			
		||||
    goto not_allowed;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -927,9 +996,7 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv
 | 
			
		|||
  subguid.prefix = pp->e.guid.prefix;
 | 
			
		||||
  memset (&group_guid, 0, sizeof (group_guid));
 | 
			
		||||
 | 
			
		||||
  /* SPDP writer */
 | 
			
		||||
  /* Note: skip SEDP <=> skip SPDP because of the way ddsi_discovery.c does things
 | 
			
		||||
     currently.  */
 | 
			
		||||
  /* SPDP is very much special and must be done first */
 | 
			
		||||
  if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS))
 | 
			
		||||
  {
 | 
			
		||||
    subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER);
 | 
			
		||||
| 
						 | 
				
			
			@ -938,70 +1005,15 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv
 | 
			
		|||
    whc_free_wrinfo (wrinfo);
 | 
			
		||||
    /* But we need the as_disc address set for SPDP, because we need to
 | 
			
		||||
       send it to everyone regardless of the existence of readers. */
 | 
			
		||||
    force_as_disc_address(gv, &subguid);
 | 
			
		||||
    force_as_disc_address (gv, &subguid);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Make it globally visible, else the endpoint matching won't work. */
 | 
			
		||||
  entidx_insert_participant_guid (gv->entity_index, pp);
 | 
			
		||||
 | 
			
		||||
  /* SEDP writers: */
 | 
			
		||||
  wrinfo = whc_make_wrinfo (NULL, &gv->builtin_endpoint_xqos_wr);
 | 
			
		||||
  if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS))
 | 
			
		||||
  {
 | 
			
		||||
    subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER);
 | 
			
		||||
    new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER;
 | 
			
		||||
 | 
			
		||||
    subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER);
 | 
			
		||||
    new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (gv->config.do_topic_discovery)
 | 
			
		||||
  {
 | 
			
		||||
    /* TODO: make this one configurable, we don't want all participants to publish all topics (or even just those that they use themselves) */
 | 
			
		||||
    subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER);
 | 
			
		||||
    new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* PMD writer: */
 | 
			
		||||
  if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS))
 | 
			
		||||
  {
 | 
			
		||||
    subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER);
 | 
			
		||||
    new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  whc_free_wrinfo (wrinfo);
 | 
			
		||||
 | 
			
		||||
  /* SPDP, SEDP, PMD readers: */
 | 
			
		||||
  if (!(flags & RTPS_PF_NO_BUILTIN_READERS))
 | 
			
		||||
  {
 | 
			
		||||
    subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER);
 | 
			
		||||
    new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->spdp_endpoint_xqos, NULL, NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR;
 | 
			
		||||
 | 
			
		||||
    subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER);
 | 
			
		||||
    new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR;
 | 
			
		||||
 | 
			
		||||
    subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER);
 | 
			
		||||
    new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_DETECTOR;
 | 
			
		||||
 | 
			
		||||
    subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER);
 | 
			
		||||
    new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL);
 | 
			
		||||
    pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#ifdef DDSI_INCLUDE_SECURITY
 | 
			
		||||
  if (q_omg_participant_is_secure(pp))
 | 
			
		||||
  {
 | 
			
		||||
    add_security_builtin_endpoints(pp, &subguid, &group_guid, gv, !(flags & RTPS_PF_NO_BUILTIN_WRITERS), !(flags & RTPS_PF_NO_BUILTIN_READERS));
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  /* add all built-in endpoints other than the SPDP writer */
 | 
			
		||||
  add_builtin_endpoints (pp, &subguid, &group_guid, gv, !(flags & RTPS_PF_NO_BUILTIN_WRITERS), !(flags & RTPS_PF_NO_BUILTIN_READERS));
 | 
			
		||||
 | 
			
		||||
  /* If the participant doesn't have the full set of builtin writers
 | 
			
		||||
     it depends on the privileged participant, which must exist, hence
 | 
			
		||||
| 
						 | 
				
			
			@ -1009,7 +1021,8 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv
 | 
			
		|||
     If it is the privileged participant, set the global variable
 | 
			
		||||
     pointing to it.
 | 
			
		||||
     Except when the participant is only locally available. */
 | 
			
		||||
  if (!(flags & RTPS_PF_ONLY_LOCAL)) {
 | 
			
		||||
  if (!(flags & RTPS_PF_ONLY_LOCAL))
 | 
			
		||||
  {
 | 
			
		||||
    ddsrt_mutex_lock (&gv->privileged_pp_lock);
 | 
			
		||||
    if ((pp->bes & builtin_writers_besmask) != builtin_writers_besmask)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -1066,16 +1079,16 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
#ifdef DDSI_INCLUDE_SECURITY
 | 
			
		||||
  if (q_omg_participant_is_secure(pp))
 | 
			
		||||
  if (q_omg_participant_is_secure (pp))
 | 
			
		||||
  {
 | 
			
		||||
    connect_participant_secure (gv, pp);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  return ret;
 | 
			
		||||
 | 
			
		||||
#ifdef DDSI_INCLUDE_SECURITY
 | 
			
		||||
not_allowed:
 | 
			
		||||
new_pp_err_secprop:
 | 
			
		||||
  if (ppconn)
 | 
			
		||||
    ddsi_conn_free (ppconn);
 | 
			
		||||
  ddsi_plist_fini (pp->plist);
 | 
			
		||||
  ddsrt_free (pp->plist);
 | 
			
		||||
  inverse_uint32_set_fini (&pp->avail_entityids.x);
 | 
			
		||||
| 
						 | 
				
			
			@ -1085,7 +1098,6 @@ new_pp_err_secprop:
 | 
			
		|||
  ddsrt_mutex_lock (&gv->participant_set_lock);
 | 
			
		||||
  gv->nparticipants--;
 | 
			
		||||
  ddsrt_mutex_unlock (&gv->participant_set_lock);
 | 
			
		||||
#endif
 | 
			
		||||
new_pp_err:
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4886,6 +4898,7 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp
 | 
			
		|||
  const bool is_secure = ((bes & NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER) != 0);
 | 
			
		||||
  assert (!is_secure || (plist->present & PP_IDENTITY_TOKEN));
 | 
			
		||||
  assert (is_secure || (bes & ~NN_BES_MASK_NON_SECURITY) == 0);
 | 
			
		||||
  (void) is_secure;
 | 
			
		||||
 | 
			
		||||
  assert (ppguid->entityid.u == NN_ENTITYID_PARTICIPANT);
 | 
			
		||||
  assert (entidx_lookup_proxy_participant_guid (gv->entity_index, ppguid) == NULL);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue