diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index ccb6a25..fb8785f 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -18,6 +18,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_raweth.c ddsi_ipaddr.c ddsi_mcgroup.c + ddsi_security_omg.c ddsi_serdata.c ddsi_serdata_default.c ddsi_sertopic.c @@ -70,6 +71,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_ipaddr.h ddsi_mcgroup.h ddsi_plist_generic.h + ddsi_security_omg.h ddsi_serdata.h ddsi_sertopic.h ddsi_serdata_default.h diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h new file mode 100644 index 0000000..298370f --- /dev/null +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -0,0 +1,152 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSI_OMG_SECURITY_H +#define DDSI_OMG_SECURITY_H + +#include "dds/ddsi/q_entity.h" +#include "dds/ddsi/q_plist.h" +#include "dds/ddsi/q_globals.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#ifdef DDSI_INCLUDE_SECURITY + +/** + * @brief Check if security is enabled for the participant. + * + * @param[in] pp Participant to check if it is secure. + * + * @returns bool + * @retval true Participant is secure + * @retval false Participant is not secure + */ +bool q_omg_participant_is_secure(const struct participant *pp); + +/** + * @brief Get security info flags of the given writer. + * + * @param[in] wr Writer to get the security info from. + * @param[out] info The security info. + * + * @returns bool + * @retval true Security info set. + * @retval false Security info not set (probably unsecure writer). + */ +bool q_omg_get_writer_security_info(const struct writer *wr, nn_security_info_t *info); + +/** + * @brief Get security info flags of the given reader. + * + * @param[in] rd Reader to get the security info from. + * @param[out] info The security info. + * + * @returns bool + * @retval true Security info set. + * @retval false Security info not set (probably unsecure reader). + */ +bool q_omg_get_reader_security_info(const struct reader *rd, nn_security_info_t *info); + +/** + * @brief Return the builtin writer id for this readers' discovery. + * + * Return builtin entity id of the writer to use for the subscription + * discovery information. + * Depending on whether the discovery is protected or not (for the + * given reader), either the default writer or protected writer needs + * to be used. + * + * @param[in] rd Reader to determine the subscription writer from. + * + * @returns unsigned + * @retval NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER + * @retval NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER + */ +unsigned determine_subscription_writer(const struct reader *rd); + +/** + * @brief Return the builtin writer id for this writers' discovery. + * + * Return builtin entity id of the writer to use for the publication + * discovery information. + * Depending on whether the discovery is protected or not (for the + * given writer), either the default writer or protected writer needs + * to be used. + * + * @param[in] wr Writer to determine the publication writer from. + * + * @returns unsigned + * @retval NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER + * @retval NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER + */ +unsigned determine_publication_writer(const struct writer *wr); + +/** + * @brief Determine if the proxy participant is allowed to be deleted + * by the given writer. + * + * If an proxy participant is authenticated, it is only allowed to + * to deleted when a dispose is received from the proper protected + * discovery writer. + * + * @param[in] gv Used for tracing. + * @param[in] guid Guid of the proxy participant to be deleted. + * @param[in] pwr_entityid Writer that send the dispose. + * + * @returns bool + * @retval true The proxy participant may be deleted. + * @retval false The proxy participant may not be deleted by this writer. + */ +bool allow_proxy_participant_deletion(struct q_globals * const gv, const struct ddsi_guid *guid, const ddsi_entityid_t pwr_entityid); + +#else /* DDSI_INCLUDE_SECURITY */ + +#include "dds/ddsi/q_unused.h" + +inline bool +q_omg_participant_is_secure( + UNUSED_ARG(const struct participant *pp)) +{ + return false; +} + +inline unsigned +determine_subscription_writer( + UNUSED_ARG(const struct reader *rd)) +{ + return NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER; +} + +inline unsigned +determine_publication_writer( + UNUSED_ARG(const struct writer *wr)) +{ + return NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER; +} + +inline bool +allow_proxy_participant_deletion( + UNUSED_ARG(struct q_globals * const gv), + UNUSED_ARG(const struct ddsi_guid *guid), + UNUSED_ARG(const ddsi_entityid_t pwr_entityid)) +{ + return true; +} + +#endif /* DDSI_INCLUDE_SECURITY */ + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSI_OMG_SECURITY_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index c14b490..c5cff1a 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -237,6 +237,10 @@ struct q_globals { dds_qos_t spdp_endpoint_xqos; dds_qos_t builtin_endpoint_xqos_rd; dds_qos_t builtin_endpoint_xqos_wr; +#ifdef DDSI_INCLUDE_SECURITY + dds_qos_t builtin_stateless_xqos_rd; + dds_qos_t builtin_stateless_xqos_wr; +#endif /* SPDP packets get very special treatment (they're the only packets we accept from writers we don't know) and have their very own diff --git a/src/core/ddsi/include/dds/ddsi/q_plist.h b/src/core/ddsi/include/dds/ddsi/q_plist.h index 5f82529..561bdbf 100644 --- a/src/core/ddsi/include/dds/ddsi/q_plist.h +++ b/src/core/ddsi/include/dds/ddsi/q_plist.h @@ -172,6 +172,9 @@ typedef struct nn_security_info #define NN_PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_RTPS_AUTHENTICATED (1u << 3) #define NN_PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_DISCOVERY_AUTHENTICATED (1u << 4) #define NN_PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_AUTHENTICATED (1u << 5) +#else +struct nn_security_info; +typedef struct nn_security_info nn_security_info_t; #endif diff --git a/src/core/ddsi/include/dds/ddsi/q_protocol.h b/src/core/ddsi/include/dds/ddsi/q_protocol.h index 9ebf7c5..0fbbc64 100644 --- a/src/core/ddsi/include/dds/ddsi/q_protocol.h +++ b/src/core/ddsi/include/dds/ddsi/q_protocol.h @@ -89,6 +89,19 @@ typedef struct { #define NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER (1u << 12) #define NN_DISC_BUILTIN_ENDPOINT_TOPIC_DETECTOR (1u << 13) +/* Security extensions: */ +#define NN_BUILTIN_ENDPOINT_PUBLICATION_MESSAGE_SECURE_ANNOUNCER (1u<<16) +#define NN_BUILTIN_ENDPOINT_PUBLICATION_MESSAGE_SECURE_DETECTOR (1u<<17) +#define NN_BUILTIN_ENDPOINT_SUBSCRIPTION_MESSAGE_SECURE_ANNOUNCER (1u<<18) +#define NN_BUILTIN_ENDPOINT_SUBSCRIPTION_MESSAGE_SECURE_DETECTOR (1u<<19) +#define NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_ANNOUNCER (1u<<20) +#define NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_DETECTOR (1u<<21) +#define NN_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_ANNOUNCER (1u<<22) +#define NN_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_DETECTOR (1u<<23) +/* TODO: ENDPOINT_PARTICIPANT_VOLATILE */ +#define NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER (1u << 26) +#define NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_DETECTOR (1u << 27) + /* PrismTech extensions: */ #define NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER (1u << 0) #define NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_READER (1u << 1) diff --git a/src/core/ddsi/include/dds/ddsi/q_rtps.h b/src/core/ddsi/include/dds/ddsi/q_rtps.h index dfe0d39..71382f4 100644 --- a/src/core/ddsi/include/dds/ddsi/q_rtps.h +++ b/src/core/ddsi/include/dds/ddsi/q_rtps.h @@ -44,6 +44,19 @@ typedef int64_t seqno_t; #define NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER 0x100c7 #define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER 0x200c2 #define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER 0x200c7 + +#define NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER 0xff0003c2 +#define NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_READER 0xff0003c7 +#define NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER 0xff0004c2 +#define NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_READER 0xff0004c7 +#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER 0x201c3 +#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_READER 0x201c4 +#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER 0xff0200c2 +#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_READER 0xff0200c7 +/* TODO: ENDPOINT_PARTICIPANT_VOLATILE */ +#define NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER 0xff0101c2 +#define NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_READER 0xff0101c7 + #define NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER 0x142 #define NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER 0x147 #define NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER 0x242 diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c new file mode 100644 index 0000000..8e04eb3 --- /dev/null +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -0,0 +1,148 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifdef DDSI_INCLUDE_SECURITY + +#include + +#include "dds/ddsrt/misc.h" + +#include "dds/ddsi/q_unused.h" +#include "dds/ddsi/ddsi_security_omg.h" + +bool +q_omg_participant_is_secure( + const struct participant *pp) +{ + /* TODO: Register local participant. */ + DDSRT_UNUSED_ARG(pp); + return false; +} + +static bool +q_omg_writer_is_discovery_protected( + const struct writer *wr) +{ + /* TODO: Register local writer. */ + DDSRT_UNUSED_ARG(wr); + return false; +} + +static bool +q_omg_reader_is_discovery_protected( + const struct reader *rd) +{ + /* TODO: Register local reader. */ + DDSRT_UNUSED_ARG(rd); + return false; +} + +bool +q_omg_get_writer_security_info( + const struct writer *wr, + nn_security_info_t *info) +{ + assert(wr); + assert(info); + /* TODO: Register local writer. */ + DDSRT_UNUSED_ARG(wr); + info->plugin_security_attributes = 0; + info->security_attributes = 0; + return false; +} + +bool +q_omg_get_reader_security_info( + const struct reader *rd, + nn_security_info_t *info) +{ + assert(rd); + assert(info); + /* TODO: Register local reader. */ + DDSRT_UNUSED_ARG(rd); + info->plugin_security_attributes = 0; + info->security_attributes = 0; + return false; +} + +static bool +q_omg_proxyparticipant_is_authenticated( + struct proxy_participant *proxypp) +{ + /* TODO: Handshake */ + DDSRT_UNUSED_ARG(proxypp); + return false; +} + +unsigned +determine_subscription_writer( + const struct reader *rd) +{ + if (q_omg_reader_is_discovery_protected(rd)) + { + return NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER; + } + return NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER; +} + +unsigned +determine_publication_writer( + const struct writer *wr) +{ + if (q_omg_writer_is_discovery_protected(wr)) + { + return NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER; + } + return NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER; +} + +bool +allow_proxy_participant_deletion( + struct q_globals * const gv, + const struct ddsi_guid *guid, + const ddsi_entityid_t pwr_entityid) +{ + struct proxy_participant *proxypp; + + assert(gv); + assert(guid); + + /* Always allow deletion from a secure proxy writer. */ + if (pwr_entityid.u == NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER) + return true; + + /* Not from a secure proxy writer. + * Only allow deletion when proxy participant is not authenticated. */ + proxypp = ephash_lookup_proxy_participant_guid(gv->guid_hash, guid); + if (!proxypp) + { + GVLOGDISC (" unknown"); + return false; + } + return (!q_omg_proxyparticipant_is_authenticated(proxypp)); +} + + +#else /* DDSI_INCLUDE_SECURITY */ + +#include "dds/ddsi/ddsi_security_omg.h" + +extern inline bool q_omg_participant_is_secure(UNUSED_ARG(const struct participant *pp)); + +extern inline unsigned determine_subscription_writer(UNUSED_ARG(const struct reader *rd)); +extern inline unsigned determine_publication_writer(UNUSED_ARG(const struct writer *wr)); + +extern inline bool allow_proxy_participant_deletion( + UNUSED_ARG(struct q_globals * const gv), + UNUSED_ARG(const struct ddsi_guid *guid), + UNUSED_ARG(const ddsi_entityid_t pwr_entityid)); + +#endif /* DDSI_INCLUDE_SECURITY */ diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 74d025a..d6f2137 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -43,6 +43,7 @@ #include "dds/ddsi/q_lease.h" #include "dds/ddsi/ddsi_serdata_default.h" #include "dds/ddsi/q_feature_check.h" +#include "dds/ddsi/ddsi_security_omg.h" static int get_locator (const struct q_globals *gv, nn_locator_t *loc, const nn_locators_t *locs, int uc_same_subnet) { @@ -327,16 +328,18 @@ int spdp_write (struct participant *pp) return ret; } -int spdp_dispose_unregister (struct participant *pp) +static int spdp_dispose_unregister_with_wr (struct participant *pp, unsigned entityid) { struct nn_xmsg *mpayload; nn_plist_t ps; struct writer *wr; int ret; - if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) + if ((wr = get_builtin_writer (pp, entityid)) == NULL) { - ETRACE (pp, "spdp_dispose_unregister("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid)); + ETRACE (pp, "spdp_dispose_unregister("PGUIDFMT") - builtin participant %s writer not found\n", + PGUID (pp->e.guid), + entityid == NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER ? "secure" : ""); return 0; } @@ -353,6 +356,21 @@ int spdp_dispose_unregister (struct participant *pp) return ret; } +int spdp_dispose_unregister (struct participant *pp) +{ + /* + * When disposing a participant, it should be announced on both the + * non-secure and secure writers. + * The receiver will decide from which writer it accepts the dispose. + */ + int ret = spdp_dispose_unregister_with_wr(pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER); + if ((ret > 0) && q_omg_participant_is_secure(pp)) + { + ret = spdp_dispose_unregister_with_wr(pp, NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER); + } + return ret; +} + static unsigned pseudo_random_delay (const ddsi_guid_t *x, const ddsi_guid_t *y, nn_mtime_t tnow) { /* You know, an ordinary random generator would be even better, but @@ -407,7 +425,7 @@ static void respond_to_spdp (const struct q_globals *gv, const ddsi_guid_t *dest ephash_enum_participant_fini (&est); } -static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t timestamp, const nn_plist_t *datap, unsigned statusinfo) +static int handle_SPDP_dead (const struct receiver_state *rst, ddsi_entityid_t pwr_entityid, nn_wctime_t timestamp, const nn_plist_t *datap, unsigned statusinfo) { struct q_globals * const gv = rst->gv; ddsi_guid_t guid; @@ -419,13 +437,20 @@ static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t times guid = datap->participant_guid; GVLOGDISC (" %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (guid)); assert (guid.entityid.u == NN_ENTITYID_PARTICIPANT); - if (delete_proxy_participant_by_guid (gv, &guid, timestamp, 0) < 0) + if (allow_proxy_participant_deletion(gv, &guid, pwr_entityid)) { - GVLOGDISC (" unknown"); + if (delete_proxy_participant_by_guid (gv, &guid, timestamp, 0) < 0) + { + GVLOGDISC (" unknown"); + } + else + { + GVLOGDISC (" delete"); + } } else { - GVLOGDISC (" delete"); + GVLOGDISC (" not allowed"); } } else @@ -793,7 +818,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ return 1; } -static void handle_SPDP (const struct receiver_state *rst, seqno_t seq, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) +static void handle_SPDP (const struct receiver_state *rst, ddsi_entityid_t pwr_entityid, seqno_t seq, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) { struct q_globals * const gv = rst->gv; const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ @@ -832,7 +857,7 @@ static void handle_SPDP (const struct receiver_state *rst, seqno_t seq, nn_wctim case NN_STATUSINFO_DISPOSE: case NN_STATUSINFO_UNREGISTER: case (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER): - interesting = handle_SPDP_dead (rst, timestamp, &decoded_data, statusinfo); + interesting = handle_SPDP_dead (rst, pwr_entityid, timestamp, &decoded_data, statusinfo); break; } @@ -888,7 +913,7 @@ static int sedp_write_endpoint ( struct writer *wr, int alive, const ddsi_guid_t *epguid, const struct entity_common *common, const struct endpoint_common *epcommon, - const dds_qos_t *xqos, struct addrset *as) + const dds_qos_t *xqos, struct addrset *as, nn_security_info_t *security) { struct q_globals * const gv = wr->e.gv; const dds_qos_t *defqos = is_writer_entityid (epguid->entityid) ? &gv->default_xqos_wr : &gv->default_xqos_rd; @@ -908,6 +933,17 @@ static int sedp_write_endpoint ps.entity_name = common->name; } +#ifdef DDSI_INCLUDE_SECURITY + if (security) + { + ps.present |= PP_ENDPOINT_SECURITY_INFO; + memcpy(&ps.endpoint_security_info, security, sizeof(nn_security_info_t)); + } +#else + (void)security; + assert(security == NULL); +#endif + if (!alive) { assert (xqos == NULL); @@ -987,13 +1023,22 @@ int sedp_write_writer (struct writer *wr) { if ((!is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE)) && (!wr->e.onlylocal)) { - struct writer *sedp_wr = get_sedp_writer (wr->c.pp, NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER); + unsigned entityid = determine_publication_writer(wr); + struct writer *sedp_wr = get_sedp_writer (wr->c.pp, entityid); + nn_security_info_t *security = NULL; #ifdef DDSI_INCLUDE_SSM struct addrset *as = wr->ssm_as; #else struct addrset *as = NULL; #endif - return sedp_write_endpoint (sedp_wr, 1, &wr->e.guid, &wr->e, &wr->c, wr->xqos, as); +#ifdef DDSI_INCLUDE_SECURITY + nn_security_info_t tmp; + if (q_omg_get_writer_security_info(wr, &tmp)) + { + security = &tmp; + } +#endif + return sedp_write_endpoint (sedp_wr, 1, &wr->e.guid, &wr->e, &wr->c, wr->xqos, as, security); } return 0; } @@ -1002,13 +1047,22 @@ int sedp_write_reader (struct reader *rd) { if ((!is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE)) && (!rd->e.onlylocal)) { - struct writer *sedp_wr = get_sedp_writer (rd->c.pp, NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER); + unsigned entityid = determine_subscription_writer(rd); + struct writer *sedp_wr = get_sedp_writer (rd->c.pp, entityid); + nn_security_info_t *security = NULL; #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS struct addrset *as = rd->as; #else struct addrset *as = NULL; #endif - return sedp_write_endpoint (sedp_wr, 1, &rd->e.guid, &rd->e, &rd->c, rd->xqos, as); +#ifdef DDSI_INCLUDE_SECURITY + nn_security_info_t tmp; + if (q_omg_get_reader_security_info(rd, &tmp)) + { + security = &tmp; + } +#endif + return sedp_write_endpoint (sedp_wr, 1, &rd->e.guid, &rd->e, &rd->c, rd->xqos, as, security); } return 0; } @@ -1017,8 +1071,9 @@ int sedp_dispose_unregister_writer (struct writer *wr) { if ((!is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE)) && (!wr->e.onlylocal)) { - struct writer *sedp_wr = get_sedp_writer (wr->c.pp, NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER); - return sedp_write_endpoint (sedp_wr, 0, &wr->e.guid, NULL, NULL, NULL, NULL); + unsigned entityid = determine_publication_writer(wr); + struct writer *sedp_wr = get_sedp_writer (wr->c.pp, entityid); + return sedp_write_endpoint (sedp_wr, 0, &wr->e.guid, NULL, NULL, NULL, NULL, NULL); } return 0; } @@ -1027,8 +1082,9 @@ int sedp_dispose_unregister_reader (struct reader *rd) { if ((!is_builtin_entityid(rd->e.guid.entityid, NN_VENDORID_ECLIPSE)) && (!rd->e.onlylocal)) { - struct writer *sedp_wr = get_sedp_writer (rd->c.pp, NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER); - return sedp_write_endpoint (sedp_wr, 0, &rd->e.guid, NULL, NULL, NULL, NULL); + unsigned entityid = determine_subscription_writer(rd); + struct writer *sedp_wr = get_sedp_writer (rd->c.pp, entityid); + return sedp_write_endpoint (sedp_wr, 0, &rd->e.guid, NULL, NULL, NULL, NULL, NULL); } return 0; } @@ -1594,7 +1650,13 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str pwr = sampleinfo->pwr; if (pwr == NULL) - assert (srcguid.entityid.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER); + { + /* NULL with NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER is normal. It is possible that + * NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER has NULL as well if there + * is a security mismatch being handled. */ + assert ((srcguid.entityid.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) || + (srcguid.entityid.u == NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER)); + } else { assert (is_builtin_entityid (pwr->e.guid.entityid, pwr->c.vendor)); @@ -1690,6 +1752,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str { case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER: + case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER: pid = PID_PARTICIPANT_GUID; break; case NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER: @@ -1698,6 +1761,8 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str break; case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER: pid = PID_ENDPOINT_GUID; break; case NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER: @@ -1736,18 +1801,27 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str switch (srcguid.entityid.u) { case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: - handle_SPDP (sampleinfo->rst, sampleinfo->seq, timestamp, statusinfo, datap, datasz); + case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER: + handle_SPDP (sampleinfo->rst, srcguid.entityid, sampleinfo->seq, timestamp, statusinfo, datap, datasz); break; case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER: handle_SEDP (sampleinfo->rst, sampleinfo->seq, timestamp, statusinfo, datap, datasz); break; case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER: handle_PMD (sampleinfo->rst, timestamp, statusinfo, datap, datasz); break; case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER: handle_SEDP_CM (sampleinfo->rst, srcguid.entityid, timestamp, statusinfo, datap, datasz); break; +#ifdef DDSI_INCLUDE_SECURITY + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER: + /* TODO: Handshake */ + break; +#endif default: GVLOGDISC ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": not handled\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index d2a4fed..e4c020d 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -48,6 +48,7 @@ #include "dds__whc.h" #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_tkmap.h" +#include "dds/ddsi/ddsi_security_omg.h" struct deleted_participant { ddsrt_avl_node_t avlnode; @@ -461,6 +462,76 @@ static void pp_release_entityid(struct participant *pp, ddsi_entityid_t id) ddsrt_mutex_unlock (&pp->e.lock); } +static void force_as_disc_address(struct q_globals *gv, const ddsi_guid_t *subguid) +{ + struct writer *wr = ephash_lookup_writer_guid (gv->guid_hash, subguid); + assert (wr != NULL); + ddsrt_mutex_lock (&wr->e.lock); + unref_addrset (wr->as); + unref_addrset (wr->as_group); + wr->as = ref_addrset (gv->as_disc); + wr->as_group = ref_addrset (gv->as_disc_group); + ddsrt_mutex_unlock (&wr->e.lock); +} + +#ifdef DDSI_INCLUDE_SECURITY +static void add_security_builtin_endpoints(struct participant *pp, ddsi_guid_t *subguid, const ddsi_guid_t *group_guid, struct q_globals *gv, bool add_writers, bool add_readers) +{ + if (add_writers) + { + subguid->entityid = to_entityid (NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER); + new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); + /* 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); + pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER; + + subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER); + new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_stateless_xqos_wr, whc_new(gv, 0, 1, 1), NULL, NULL); + pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_ANNOUNCER; + + subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER); + new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); + pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_ANNOUNCER; + + subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER); + new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); + pp->bes |= NN_BUILTIN_ENDPOINT_PUBLICATION_MESSAGE_SECURE_ANNOUNCER; + + subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER); + new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, 1, 1, 1), NULL, NULL); + pp->bes |= NN_BUILTIN_ENDPOINT_SUBSCRIPTION_MESSAGE_SECURE_ANNOUNCER; + } + + if (add_readers) + { + subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_READER); + new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + pp->bes |= NN_BUILTIN_ENDPOINT_SUBSCRIPTION_MESSAGE_SECURE_DETECTOR; + + subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_READER); + new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + pp->bes |= NN_BUILTIN_ENDPOINT_PUBLICATION_MESSAGE_SECURE_DETECTOR; + } + + /* + * When security is enabled configure the associated necessary builtin readers independent of the + * besmode flag setting, because all participant do require authentication. + */ + subguid->entityid = to_entityid (NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_READER); + new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_DETECTOR; + + subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_READER); + new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_stateless_xqos_rd, NULL, NULL, NULL); + pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_DETECTOR; + + subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_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_SECURE_DETECTOR; +} +#endif + dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals *gv, unsigned flags, const nn_plist_t *plist) { struct participant *pp; @@ -591,16 +662,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->spdp_endpoint_xqos, whc_new(gv, 1, 1, 1), LAST_WR_PARAMS); /* But we need the as_disc address set for SPDP, because we need to send it to everyone regardless of the existence of readers. */ - { - struct writer *wr = ephash_lookup_writer_guid (gv->guid_hash, &subguid); - assert (wr != NULL); - ddsrt_mutex_lock (&wr->e.lock); - unref_addrset (wr->as); - unref_addrset (wr->as_group); - wr->as = ref_addrset (gv->as_disc); - wr->as_group = ref_addrset (gv->as_disc_group); - ddsrt_mutex_unlock (&wr->e.lock); - } + force_as_disc_address(gv, &subguid); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER; } @@ -679,6 +741,14 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct q_globals * pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_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 + #undef LAST_WR_PARAMS /* If the participant doesn't have the full set of builtin writers @@ -830,6 +900,17 @@ static void unref_participant (struct participant *pp, const struct ddsi_guid *g NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER, NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER, + /* Security ones: */ + NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER, + NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_READER, + NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER, + NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_READER, + NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER, + NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_READER, + NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER, + NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_READER, + NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER, + NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_READER, /* PrismTech ones: */ NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER, NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER, @@ -913,7 +994,7 @@ static void unref_participant (struct participant *pp, const struct ddsi_guid *g (pp->prismtech_bes & prismtech_builtin_writers_besmask) != prismtech_builtin_writers_besmask) { /* Participant doesn't have a full complement of built-in - writers, therefore, it relies on gv.privileged_pp, and + writers, therefore, it relies on gv->privileged_pp, and therefore we must decrement the reference count of that one. Why read it with the lock held, only to release it and use it @@ -1002,9 +1083,15 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: bes_mask = NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER; break; + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER: + bes_mask = NN_BUILTIN_ENDPOINT_SUBSCRIPTION_MESSAGE_SECURE_ANNOUNCER; + break; case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: bes_mask = NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER; break; + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: + bes_mask = NN_BUILTIN_ENDPOINT_PUBLICATION_MESSAGE_SECURE_ANNOUNCER; + break; case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: bes_mask = NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; break; @@ -1020,6 +1107,15 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity case NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER: bes_mask = NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER; break; + case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER: + bes_mask = NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER: + bes_mask = NN_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_ANNOUNCER; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER: + bes_mask = NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_ANNOUNCER; + break; default: DDS_FATAL ("get_builtin_writer called with entityid %x\n", entityid); return NULL; @@ -1385,7 +1481,7 @@ void rebuild_or_clear_writer_addrsets (struct q_globals *gv, int rebuild) else { /* SPDP writers have no matched readers, instead they all use the same address space, - gv.as_disc. Keep as_disc unchanged, and instead make the participants point to the + gv->as_disc. Keep as_disc unchanged, and instead make the participants point to the empty one. */ unref_addrset(wr->as); if (rebuild) @@ -2112,6 +2208,13 @@ static ddsi_entityid_t builtin_entityid_match (ddsi_entityid_t x) res.u = NN_ENTITYID_UNKNOWN; break; + case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER: + res.u = NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_READER; + break; + case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_READER: + res.u = NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER; + break; + case NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER: res.u = NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER; break; @@ -2130,6 +2233,30 @@ static ddsi_entityid_t builtin_entityid_match (ddsi_entityid_t x) case NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER: res.u = NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER; break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER: + res.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_READER; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_READER: + res.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER: + res.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_READER; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_READER: + res.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER; + break; + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: + res.u = NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_READER; + break; + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_READER: + res.u = NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER; + break; + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER: + res.u = NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_READER; + break; + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_READER: + res.u = NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER; + break; default: assert (0); @@ -2815,7 +2942,8 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se if (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE)) { assert (wr->xqos->history.kind == DDS_HISTORY_KEEP_LAST); - assert (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL); + assert (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL || + wr->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER); } wr->handle_as_transient_local = (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL); wr->include_keyhash = @@ -3614,6 +3742,158 @@ void proxy_participant_reassign_lease (struct proxy_participant *proxypp, struct ddsrt_mutex_unlock (&proxypp->e.lock); } +struct bestab { + unsigned besflag; + unsigned prismtech_besflag; + unsigned entityid; +}; + +static void create_proxy_builtin_endpoints( + struct q_globals *gv, + const struct bestab *bestab, + int nbes, + const struct ddsi_guid *ppguid, + struct proxy_participant *proxypp, + nn_wctime_t timestamp, + dds_qos_t *xqos_wr, + dds_qos_t *xqos_rd) +{ + nn_plist_t plist_rd, plist_wr; + int i; + /* Note: no entity name or group GUID supplied, but that shouldn't + * matter, as these are internal to DDSI and don't use group + * coherency + */ + nn_plist_init_empty (&plist_wr); + nn_plist_init_empty (&plist_rd); + nn_xqos_copy (&plist_wr.qos, xqos_wr); + nn_xqos_copy (&plist_rd.qos, xqos_rd); + for (i = 0; i < nbes; i++) + { + const struct bestab *te = &bestab[i]; + if ((proxypp->bes & te->besflag) || (proxypp->prismtech_bes & te->prismtech_besflag)) + { + ddsi_guid_t guid1; + guid1.prefix = proxypp->e.guid.prefix; + guid1.entityid.u = te->entityid; + assert (is_builtin_entityid (guid1.entityid, proxypp->vendor)); + if (is_writer_entityid (guid1.entityid)) + { + new_proxy_writer (gv, ppguid, &guid1, proxypp->as_meta, &plist_wr, gv->builtins_dqueue, gv->xevents, timestamp, 0); + } + else + { +#ifdef DDSI_INCLUDE_SSM + const int ssm = addrset_contains_ssm (gv, proxypp->as_meta); +#else + const int ssm = 0; +#endif + new_proxy_reader (gv, ppguid, &guid1, proxypp->as_meta, &plist_rd, timestamp, 0, ssm); + } + } + } + nn_plist_fini (&plist_wr); + nn_plist_fini (&plist_rd); +} + + +static void add_proxy_builtin_endpoints( + struct q_globals *gv, + const struct ddsi_guid *ppguid, + struct proxy_participant *proxypp, + nn_wctime_t timestamp) +{ + /* Add proxy endpoints based on the advertised (& possibly augmented + ...) built-in endpoint set. */ +#define PT_TE(ap_, a_, bp_, b_) { 0, NN_##ap_##BUILTIN_ENDPOINT_##a_, NN_ENTITYID_##bp_##_BUILTIN_##b_ } +#define TE(ap_, a_, bp_, b_) { NN_##ap_##BUILTIN_ENDPOINT_##a_, 0, NN_ENTITYID_##bp_##_BUILTIN_##b_ } +#define LTE(a_, bp_, b_) { NN_##BUILTIN_ENDPOINT_##a_, 0, NN_ENTITYID_##bp_##_BUILTIN_##b_ } + + /* 'Default' proxy endpoints. */ + static const struct bestab bestab_default[] = { +#if 0 + /* SPDP gets special treatment => no need for proxy + writers/readers */ + TE (DISC_, PARTICIPANT_ANNOUNCER, SPDP, PARTICIPANT_WRITER), +#endif + TE (DISC_, PARTICIPANT_DETECTOR, SPDP, PARTICIPANT_READER), + TE (DISC_, PUBLICATION_ANNOUNCER, SEDP, PUBLICATIONS_WRITER), + TE (DISC_, PUBLICATION_DETECTOR, SEDP, PUBLICATIONS_READER), + TE (DISC_, SUBSCRIPTION_ANNOUNCER, SEDP, SUBSCRIPTIONS_WRITER), + TE (DISC_, SUBSCRIPTION_DETECTOR, SEDP, SUBSCRIPTIONS_READER), + LTE (PARTICIPANT_MESSAGE_DATA_WRITER, P2P, PARTICIPANT_MESSAGE_WRITER), + LTE (PARTICIPANT_MESSAGE_DATA_READER, P2P, PARTICIPANT_MESSAGE_READER), + TE (DISC_, TOPIC_ANNOUNCER, SEDP, TOPIC_WRITER), + TE (DISC_, TOPIC_DETECTOR, SEDP, TOPIC_READER), + PT_TE (DISC_, CM_PARTICIPANT_READER, SEDP, CM_PARTICIPANT_READER), + PT_TE (DISC_, CM_PARTICIPANT_WRITER, SEDP, CM_PARTICIPANT_WRITER), + PT_TE (DISC_, CM_PUBLISHER_READER, SEDP, CM_PUBLISHER_READER), + PT_TE (DISC_, CM_PUBLISHER_WRITER, SEDP, CM_PUBLISHER_WRITER), + PT_TE (DISC_, CM_SUBSCRIBER_READER, SEDP, CM_SUBSCRIBER_READER), + PT_TE (DISC_, CM_SUBSCRIBER_WRITER, SEDP, CM_SUBSCRIBER_WRITER) + }; + create_proxy_builtin_endpoints(gv, + bestab_default, + (int)(sizeof (bestab_default) / sizeof (*bestab_default)), + ppguid, + proxypp, + timestamp, + &gv->builtin_endpoint_xqos_wr, + &gv->builtin_endpoint_xqos_rd); + +#ifdef DDSI_INCLUDE_SECURITY + /* Security 'default' proxy endpoints. */ + static const struct bestab bestab_security[] = { + LTE (PUBLICATION_MESSAGE_SECURE_ANNOUNCER, SEDP, PUBLICATIONS_SECURE_WRITER), + LTE (PUBLICATION_MESSAGE_SECURE_DETECTOR, SEDP, PUBLICATIONS_SECURE_READER), + LTE (SUBSCRIPTION_MESSAGE_SECURE_ANNOUNCER, SEDP, SUBSCRIPTIONS_SECURE_WRITER), + LTE (SUBSCRIPTION_MESSAGE_SECURE_DETECTOR, SEDP, SUBSCRIPTIONS_SECURE_READER), + LTE (PARTICIPANT_MESSAGE_SECURE_ANNOUNCER, P2P, PARTICIPANT_MESSAGE_SECURE_WRITER), + LTE (PARTICIPANT_MESSAGE_SECURE_DETECTOR, P2P, PARTICIPANT_MESSAGE_SECURE_READER), + TE (DISC_, PARTICIPANT_SECURE_ANNOUNCER, SPDP_RELIABLE, PARTICIPANT_SECURE_WRITER), + TE (DISC_, PARTICIPANT_SECURE_DETECTOR, SPDP_RELIABLE, PARTICIPANT_SECURE_READER) + }; + create_proxy_builtin_endpoints(gv, + bestab_security, + (int)(sizeof (bestab_security) / sizeof (*bestab_security)), + ppguid, + proxypp, + timestamp, + &gv->builtin_endpoint_xqos_wr, + &gv->builtin_endpoint_xqos_rd); + + /* Security 'stateless' proxy endpoints. */ + static const struct bestab bestab_stateless[] = { + LTE (PARTICIPANT_STATELESS_MESSAGE_ANNOUNCER, P2P, PARTICIPANT_STATELESS_MESSAGE_WRITER), + LTE (PARTICIPANT_STATELESS_MESSAGE_DETECTOR, P2P, PARTICIPANT_STATELESS_MESSAGE_READER) + }; + create_proxy_builtin_endpoints(gv, + bestab_stateless, + (int)(sizeof (bestab_stateless) / sizeof (*bestab_stateless)), + ppguid, + proxypp, + timestamp, + &gv->builtin_stateless_xqos_wr, + &gv->builtin_stateless_xqos_rd); +#endif + + /* Register lease, but be careful not to accidentally re-register + DDSI2's lease, as we may have become dependent on DDSI2 any time + after ephash_insert_proxy_participant_guid even if + privileged_pp_guid was NULL originally */ + ddsrt_mutex_lock (&proxypp->e.lock); + + if (proxypp->owns_lease) + lease_register (ddsrt_atomic_ldvoidp (&proxypp->lease)); + + builtintopic_write (gv->builtin_topic_interface, &proxypp->e, timestamp, true); + ddsrt_mutex_unlock (&proxypp->e.lock); + +#undef PT_TE +#undef TE +#undef LTE +} + void new_proxy_participant ( struct q_globals *gv, @@ -3720,89 +4000,8 @@ void new_proxy_participant new_proxy_{writer,reader} to work */ ephash_insert_proxy_participant_guid (gv->guid_hash, proxypp); - /* Add proxy endpoints based on the advertised (& possibly augmented - ...) built-in endpoint set. */ - { -#define PT_TE(ap_, a_, bp_, b_) { 0, NN_##ap_##BUILTIN_ENDPOINT_##a_, NN_ENTITYID_##bp_##_BUILTIN_##b_ } -#define TE(ap_, a_, bp_, b_) { NN_##ap_##BUILTIN_ENDPOINT_##a_, 0, NN_ENTITYID_##bp_##_BUILTIN_##b_ } -#define LTE(a_, bp_, b_) { NN_##BUILTIN_ENDPOINT_##a_, 0, NN_ENTITYID_##bp_##_BUILTIN_##b_ } - static const struct bestab { - unsigned besflag; - unsigned prismtech_besflag; - unsigned entityid; - } bestab[] = { -#if 0 - /* SPDP gets special treatment => no need for proxy - writers/readers */ - TE (DISC_, PARTICIPANT_ANNOUNCER, SPDP, PARTICIPANT_WRITER), -#endif - TE (DISC_, PARTICIPANT_DETECTOR, SPDP, PARTICIPANT_READER), - TE (DISC_, PUBLICATION_ANNOUNCER, SEDP, PUBLICATIONS_WRITER), - TE (DISC_, PUBLICATION_DETECTOR, SEDP, PUBLICATIONS_READER), - TE (DISC_, SUBSCRIPTION_ANNOUNCER, SEDP, SUBSCRIPTIONS_WRITER), - TE (DISC_, SUBSCRIPTION_DETECTOR, SEDP, SUBSCRIPTIONS_READER), - LTE (PARTICIPANT_MESSAGE_DATA_WRITER, P2P, PARTICIPANT_MESSAGE_WRITER), - LTE (PARTICIPANT_MESSAGE_DATA_READER, P2P, PARTICIPANT_MESSAGE_READER), - TE (DISC_, TOPIC_ANNOUNCER, SEDP, TOPIC_WRITER), - TE (DISC_, TOPIC_DETECTOR, SEDP, TOPIC_READER), - PT_TE (DISC_, CM_PARTICIPANT_READER, SEDP, CM_PARTICIPANT_READER), - PT_TE (DISC_, CM_PARTICIPANT_WRITER, SEDP, CM_PARTICIPANT_WRITER), - PT_TE (DISC_, CM_PUBLISHER_READER, SEDP, CM_PUBLISHER_READER), - PT_TE (DISC_, CM_PUBLISHER_WRITER, SEDP, CM_PUBLISHER_WRITER), - PT_TE (DISC_, CM_SUBSCRIBER_READER, SEDP, CM_SUBSCRIBER_READER), - PT_TE (DISC_, CM_SUBSCRIBER_WRITER, SEDP, CM_SUBSCRIBER_WRITER) - }; -#undef PT_TE -#undef TE -#undef LTE - nn_plist_t plist_rd, plist_wr; - int i; - /* Note: no entity name or group GUID supplied, but that shouldn't - matter, as these are internal to DDSI and don't use group - coherency */ - nn_plist_init_empty (&plist_wr); - nn_plist_init_empty (&plist_rd); - nn_xqos_copy (&plist_wr.qos, &gv->builtin_endpoint_xqos_wr); - nn_xqos_copy (&plist_rd.qos, &gv->builtin_endpoint_xqos_rd); - for (i = 0; i < (int) (sizeof (bestab) / sizeof (*bestab)); i++) - { - const struct bestab *te = &bestab[i]; - if ((proxypp->bes & te->besflag) || (proxypp->prismtech_bes & te->prismtech_besflag)) - { - ddsi_guid_t guid1; - guid1.prefix = proxypp->e.guid.prefix; - guid1.entityid.u = te->entityid; - assert (is_builtin_entityid (guid1.entityid, proxypp->vendor)); - if (is_writer_entityid (guid1.entityid)) - { - new_proxy_writer (gv, ppguid, &guid1, proxypp->as_meta, &plist_wr, gv->builtins_dqueue, gv->xevents, timestamp, 0); - } - else - { -#ifdef DDSI_INCLUDE_SSM - const int ssm = addrset_contains_ssm (gv, proxypp->as_meta); - new_proxy_reader (gv, ppguid, &guid1, proxypp->as_meta, &plist_rd, timestamp, 0, ssm); -#else - new_proxy_reader (gv, ppguid, &guid1, proxypp->as_meta, &plist_rd, timestamp, 0); -#endif - } - } - } - nn_plist_fini (&plist_wr); - nn_plist_fini (&plist_rd); - } - - /* Register lease, but be careful not to accidentally re-register - DDSI2's lease, as we may have become dependent on DDSI2 any time - after ephash_insert_proxy_participant_guid even if - privileged_pp_guid was NULL originally */ - ddsrt_mutex_lock (&proxypp->e.lock); - - if (proxypp->owns_lease) - lease_register (ddsrt_atomic_ldvoidp (&proxypp->lease)); - - builtintopic_write (gv->builtin_topic_interface, &proxypp->e, timestamp, true); - ddsrt_mutex_unlock (&proxypp->e.lock); + /* TODO: Do security checks on the proxy participant. Either add the endpoints or delete the proxy. */ + add_proxy_builtin_endpoints(gv, ppguid, proxypp, timestamp); } int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct nn_plist *datap, enum update_proxy_participant_source source, nn_wctime_t timestamp) @@ -4104,12 +4303,27 @@ static void proxy_endpoint_common_fini (struct entity_common *e, struct proxy_en /* PROXY-WRITER ----------------------------------------------------- */ +static enum nn_reorder_mode +get_proxy_writer_reorder_mode(const ddsi_entityid_t pwr_entityid, int isreliable) +{ + if (isreliable) + { + return NN_REORDER_MODE_NORMAL; + } + if (pwr_entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER) + { + return NN_REORDER_MODE_ALWAYS_DELIVER; + } + return NN_REORDER_MODE_MONOTONICALLY_INCREASING; +} + int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, const struct ddsi_guid *guid, struct addrset *as, const nn_plist_t *plist, struct nn_dqueue *dqueue, struct xeventq *evq, nn_wctime_t timestamp, seqno_t seq) { struct proxy_participant *proxypp; struct proxy_writer *pwr; int isreliable; nn_mtime_t tnow = now_mt (); + enum nn_reorder_mode reorder_mode; assert (is_writer_entityid (guid->entityid)); assert (ephash_lookup_proxy_writer_guid (gv->guid_hash, guid) == NULL); @@ -4168,13 +4382,13 @@ int new_proxy_writer (struct q_globals *gv, const struct ddsi_guid *ppguid, cons if (isreliable) { pwr->defrag = nn_defrag_new (&gv->logconfig, NN_DEFRAG_DROP_LATEST, gv->config.defrag_reliable_maxsamples); - pwr->reorder = nn_reorder_new (&gv->logconfig, NN_REORDER_MODE_NORMAL, gv->config.primary_reorder_maxsamples, gv->config.late_ack_mode); } else { pwr->defrag = nn_defrag_new (&gv->logconfig, NN_DEFRAG_DROP_OLDEST, gv->config.defrag_unreliable_maxsamples); - pwr->reorder = nn_reorder_new (&gv->logconfig, NN_REORDER_MODE_MONOTONICALLY_INCREASING, gv->config.primary_reorder_maxsamples, gv->config.late_ack_mode); } + reorder_mode = get_proxy_writer_reorder_mode(pwr->e.guid.entityid, isreliable); + pwr->reorder = nn_reorder_new (&gv->logconfig, reorder_mode, gv->config.primary_reorder_maxsamples, gv->config.late_ack_mode); pwr->dqueue = dqueue; pwr->evq = evq; pwr->ddsi2direct_cb = 0; diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index f2bb0d9..0e2442a 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -1013,6 +1013,12 @@ int rtps_init (struct q_globals *gv) gv->spdp_endpoint_xqos.durability.kind = DDS_DURABILITY_TRANSIENT_LOCAL; make_builtin_endpoint_xqos (&gv->builtin_endpoint_xqos_rd, &gv->default_xqos_rd); make_builtin_endpoint_xqos (&gv->builtin_endpoint_xqos_wr, &gv->default_xqos_wr); +#ifdef DDSI_INCLUDE_SECURITY + nn_xqos_copy (&gv->builtin_stateless_xqos_rd, &gv->default_xqos_rd); + nn_xqos_copy (&gv->builtin_stateless_xqos_wr, &gv->default_xqos_wr); + gv->builtin_stateless_xqos_wr.reliability.kind = DDS_RELIABILITY_BEST_EFFORT; + gv->builtin_stateless_xqos_wr.durability.kind = DDS_DURABILITY_VOLATILE; +#endif make_special_topics (gv); @@ -1329,6 +1335,10 @@ err_unicast_sockets: ddsrt_cond_destroy (&gv->participant_set_cond); ddsrt_mutex_destroy (&gv->participant_set_lock); free_special_topics (gv); +#ifdef DDSI_INCLUDE_SECURITY + nn_xqos_fini (&gv->builtin_stateless_xqos_wr); + nn_xqos_fini (&gv->builtin_stateless_xqos_rd); +#endif nn_xqos_fini (&gv->builtin_endpoint_xqos_wr); nn_xqos_fini (&gv->builtin_endpoint_xqos_rd); nn_xqos_fini (&gv->spdp_endpoint_xqos); @@ -1657,6 +1667,10 @@ void rtps_fini (struct q_globals *gv) ddsrt_cond_destroy (&gv->participant_set_cond); free_special_topics (gv); +#ifdef DDSI_INCLUDE_SECURITY + nn_xqos_fini (&gv->builtin_stateless_xqos_wr); + nn_xqos_fini (&gv->builtin_stateless_xqos_rd); +#endif nn_xqos_fini (&gv->builtin_endpoint_xqos_wr); nn_xqos_fini (&gv->builtin_endpoint_xqos_rd); nn_xqos_fini (&gv->spdp_endpoint_xqos); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index ada45a0..352c611 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -2305,7 +2305,8 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con /* No proxy writer means nothing really gets done with, unless it is SPDP. SPDP is periodic, so oversize discovery packets would cause periodic warnings. */ - if (msg->writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) + if ((msg->writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) || + (msg->writerId.u == NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER)) { DDS_CWARNING (&rst->gv->logconfig, "dropping oversize (%"PRIu32" > %"PRIu32") SPDP sample %"PRId64" from remote writer "PGUIDFMT"\n", sampleinfo->size, rst->gv->config.max_sample_size, sampleinfo->seq, @@ -2374,7 +2375,8 @@ static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_r } rdata = nn_rdata_new (rmsg, 0, sampleinfo->size, submsg_offset, payload_offset); - if (msg->x.writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) + if ((msg->x.writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) || + (msg->x.writerId.u == NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER)) /* SPDP needs special treatment: there are no proxy writers for it and we accept data from unknown sources */ { @@ -2409,7 +2411,8 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct struct nn_rdata *rdata; unsigned submsg_offset, payload_offset; uint32_t begin, endp1; - if (msg->x.writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) + if ((msg->x.writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) || + (msg->x.writerId.u == NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER)) { DDS_CWARNING (&rst->gv->logconfig, "DATAFRAG("PGUIDFMT" #%"PRId64" -> "PGUIDFMT") - fragmented builtin data not yet supported\n", PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, fromSN (msg->x.writerSN), diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 0a99fc9..b0061fe 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -884,7 +884,9 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist res = 1; #ifndef NDEBUG - if (wr->e.guid.entityid.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER && !is_local_orphan_endpoint (&wr->e)) + if (((wr->e.guid.entityid.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) || + (wr->e.guid.entityid.u == NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER)) && + !is_local_orphan_endpoint (&wr->e)) { struct whc_state whcst; whc_get_state(wr->whc, &whcst);