diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h index 0deb8ea..68f040e 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h @@ -329,7 +329,6 @@ struct ddsi_domaingv { /* security globals */ #ifdef DDSI_INCLUDE_SECURITY struct dds_security_context *security_context; - struct dds_security_match_index *security_matches; struct ddsi_hsadmin *hsadmin; #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h index 6d5efcb..ff81274 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -55,24 +55,10 @@ typedef struct nn_msg_sec_info { int64_t dst_pp_handle; } nn_msg_sec_info_t; -struct guid_pair { - ddsi_guid_t src; - ddsi_guid_t dst; -}; -struct security_entity_match { - ddsrt_avl_node_t avlnode; - struct guid_pair guids; - bool matched; - bool tokens_sent; - int64_t crypto_handle; - DDS_Security_ParticipantCryptoTokenSeq *tokens; -}; -struct dds_security_match_index { - ddsrt_mutex_t lock; - ddsrt_avl_tree_t matches; -}; + + struct pp_proxypp_match { ddsrt_avl_node_t avlnode; @@ -718,6 +704,36 @@ void q_omg_security_deregister_remote_writer_match(const struct ddsi_domaingv *g */ void q_omg_security_set_remote_writer_crypto_tokens(struct reader *rd, const ddsi_guid_t *pwr_guid, const nn_dataholderseq_t *tokens); +/** + * @brief Release all the security resources associated with the remote writer. + * + * Cleanup security resource associated with the remote writer. + * + * @param[in] pwr The remote writer. + */ +void q_omg_security_deregister_remote_writer(const struct proxy_writer *pwr); + +/** + * @brief Set security information, depending on plist and proxy participant, + * into the given proxy reader. + * + * @param[in] prd Proxy reader to set security info on. + * @param[in] plist Paramater list, possibly contains security info. + */ +void set_proxy_reader_security_info(struct proxy_reader *prd, const ddsi_plist_t *plist); + +/** + * @brief Determine the security settings associated with the remote reader. + * + * From the security information contained in the parameter list from the remote reader + * the corresponding security settings are determined and returned in the info parameter. + * + * @param[in] prd The remote reader. + * @param[in] plist The parameter list from the remote reader. + * @param[out] info The security settings associated with the remote reader. + */ +void q_omg_get_proxy_reader_security_info(struct proxy_reader *prd, const ddsi_plist_t *plist, nn_security_info_t *info); + /** * @brief Check if the reader has the is_discovery_protected flag set * @@ -820,6 +836,15 @@ void q_omg_security_deregister_remote_reader_match(const struct ddsi_domaingv *g */ void q_omg_security_set_remote_reader_crypto_tokens(struct writer *wr, const ddsi_guid_t *prd_guid, const nn_dataholderseq_t *tokens); +/** + * @brief Release all the security resources associated with the remote reader. + * + * Cleanup security resource associated with the remote reader. + * + * @param[in] prd The remote reader. + */ +void q_omg_security_deregister_remote_reader(const struct proxy_reader *prd); + /** * @brief Encode RTPS message. * @@ -1074,7 +1099,9 @@ void q_omg_security_init( struct ddsi_domaingv *gv ); void q_omg_security_stop (struct ddsi_domaingv *gv); -void q_omg_security_deinit( struct ddsi_domaingv *gv ); +void q_omg_security_deinit (struct dds_security_context *sc ); + +void q_omg_security_free (struct ddsi_domaingv *gv); bool q_omg_is_security_loaded( struct dds_security_context *sc ); diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 0fc64d1..057cdf4 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -48,6 +48,11 @@ #define AC_NAME "Access Control" #define CRYPTO_NAME "Cryptographic" +/* TODO: This constant which determines the time pending matches are maintained + * and not used should be made a configurable parameter, + */ +#define PENDING_MATCH_EXPIRY_TIME 300 + #define EXCEPTION_LOG(sc,e,cat, ...) \ q_omg_log_exception(sc->logcfg, cat, e, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) @@ -157,6 +162,43 @@ struct participant_sec_index { ddsrt_avl_ctree_t participants; }; +/* The pending _match_index uses an avl tree to store pending_match's where the + * guid_pair is used as the key. The remote_guid is the primary key and + * the local_guid is the secondary key. The use of the remote_guid as the primary key + * is used in the function clear_pending_matches_by_remote_guid to clear the + * pending matches associated with a remote entity. + * + * The table containing the pending matches is protected by the pending_match_index:lock. + * It is allowed to access the fields (crypto_handle and tokens) of a pending_match outside + * the pending_match_index:lock provided that the pending_match is protected by the + * lock of the entity corresponding to the local_guid. + * A pending_match is either created when registering and matching an remote entity and + * the corresponding crypto tokens are not available or when the crypto tokens associated + * with a remote entity are received but it has not yet been discovered. + */ +struct guid_pair { + ddsi_guid_t remote_guid; + ddsi_guid_t local_guid; +}; + +struct pending_match { + ddsrt_avl_node_t avlnode; + ddsrt_fibheap_node_t heapnode; + struct guid_pair guids; + enum entity_kind kind; + int64_t crypto_handle; + DDS_Security_ParticipantCryptoTokenSeq *tokens; + ddsrt_mtime_t expiry; +}; + +struct pending_match_index { + ddsrt_mutex_t lock; + const struct ddsi_domaingv *gv; + ddsrt_avl_tree_t pending_matches; + ddsrt_fibheap_t expiry_timers; + struct xevent *evt; +}; + struct dds_security_context { dds_security_plugin auth_plugin; dds_security_plugin ac_plugin; @@ -168,6 +210,7 @@ struct dds_security_context { ddsrt_mutex_t omg_security_lock; uint32_t next_plugin_id; + struct pending_match_index security_matches; struct participant_sec_index partiticpant_index; const struct ddsrt_log_cfg *logcfg; @@ -178,15 +221,20 @@ typedef struct dds_security_context dds_security_context; static int compare_guid(const void *va, const void *vb); static int compare_crypto_handle (const void *va, const void *vb); static int compare_guid_pair(const void *va, const void *vb); +static int compare_pending_match_exptime (const void *va, const void *vb); + const ddsrt_avl_ctreedef_t pp_proxypp_treedef = DDSRT_AVL_CTREEDEF_INITIALIZER (offsetof (struct pp_proxypp_match, avlnode), offsetof (struct pp_proxypp_match, proxypp_guid), compare_guid, 0); const ddsrt_avl_treedef_t proxypp_pp_treedef = DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct proxypp_pp_match, avlnode), offsetof (struct proxypp_pp_match, pp_crypto_handle), compare_crypto_handle, 0); -const ddsrt_avl_treedef_t entity_match_treedef = - DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct security_entity_match, avlnode), offsetof (struct security_entity_match, guids), compare_guid_pair, 0); const ddsrt_avl_ctreedef_t participant_index_treedef = DDSRT_AVL_CTREEDEF_INITIALIZER (offsetof (struct participant_sec_attributes, avlnode), offsetof (struct participant_sec_attributes, crypto_handle), compare_crypto_handle, 0); +const ddsrt_avl_treedef_t pending_match_index_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct pending_match, avlnode), offsetof (struct pending_match, guids), compare_guid_pair, 0); + +const ddsrt_fibheap_def_t pending_match_expiry_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct pending_match, heapnode), compare_pending_match_exptime); + static int compare_crypto_handle (const void *va, const void *vb) { @@ -211,15 +259,22 @@ static int compare_guid(const void *va, const void *vb) static int compare_guid_pair(const void *va, const void *vb) { - const struct guid_pair *na = va; - const struct guid_pair *nb = vb; + const struct guid_pair *gpa = va; + const struct guid_pair *gpb = vb; int r; - if ((r = guid_compare(&na->src, &nb->src)) == 0) - r = guid_compare(&na->dst, &nb->dst); + if ((r = guid_compare(&gpa->remote_guid, &gpb->remote_guid)) == 0) + r = guid_compare(&gpa->local_guid, &gpb->local_guid); return r; } +static int compare_pending_match_exptime (const void *va, const void *vb) +{ + const struct pending_match *ma = va; + const struct pending_match *mb = vb; + return (ma->expiry.v == mb->expiry.v) ? 0 : (ma->expiry.v < mb->expiry.v) ? -1 : 1; +} + static struct dds_security_context * q_omg_security_get_secure_context(const struct participant *pp) { if (pp && pp->e.gv->security_context && q_omg_is_security_loaded(pp->e.gv->security_context)) @@ -258,97 +313,164 @@ void q_omg_log_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Secur DDS_Security_Exception_reset(exception); } -static struct security_entity_match * entity_match_new(const ddsi_guid_t *src, const ddsi_guid_t *dst) +static void free_pending_match(struct pending_match *match) { - struct security_entity_match *match; - - match = ddsrt_malloc(sizeof(*match)); - match->guids.src = *src; - match->guids.dst = *dst; - match->matched = false; - match->crypto_handle = 0; - match->tokens = NULL; - - return match; -} - -static void entity_match_free(struct security_entity_match *match) -{ - if (match) { - if (match->tokens) - DDS_Security_ParticipantCryptoTokenSeq_free(match->tokens); + if (match) + { + DDS_Security_ParticipantCryptoTokenSeq_free(match->tokens); ddsrt_free(match); } } -static struct security_entity_match * find_entity_match_locked(struct dds_security_match_index *list, const ddsi_guid_t *src, const ddsi_guid_t *dst) +static void pending_match_expiry_cb(struct xevent *xev, void *varg, ddsrt_mtime_t tnow); + +static struct pending_match * find_or_create_pending_entity_match(struct pending_match_index *index, enum entity_kind kind, const ddsi_guid_t *remote_guid, const ddsi_guid_t *local_guid, int64_t crypto_handle, DDS_Security_ParticipantCryptoTokenSeq *tokens) { - struct guid_pair guids; + struct guid_pair guids = { .remote_guid = *remote_guid, .local_guid = *local_guid}; + struct pending_match *match; + ddsrt_avl_ipath_t ipath; - guids.src = *src; - guids.dst = *dst; - - return ddsrt_avl_lookup(&entity_match_treedef, &list->matches, &guids); -} - -static struct security_entity_match * find_or_create_entity_match(struct dds_security_match_index *list, const ddsi_guid_t *src, const ddsi_guid_t *dst) -{ - struct security_entity_match *match; - - ddsrt_mutex_lock(&list->lock); - match = find_entity_match_locked(list, src, dst); - if (!match) + ddsrt_mutex_lock(&index->lock); + if ((match = ddsrt_avl_lookup_ipath(&pending_match_index_treedef, &index->pending_matches, &guids, &ipath)) == NULL) { - match = entity_match_new(src, dst); - ddsrt_avl_insert(&entity_match_treedef, &list->matches, match); + match = ddsrt_malloc(sizeof(*match)); + match->crypto_handle = 0; + match->tokens = NULL; + match->guids = guids; + match->kind = kind; + match->expiry = DDSRT_MTIME_NEVER; + ddsrt_avl_insert_ipath(&pending_match_index_treedef, &index->pending_matches, match, &ipath); } - ddsrt_mutex_unlock(&list->lock); + + if (crypto_handle) + match->crypto_handle = crypto_handle; + + if (tokens) + { + match->tokens = tokens; + match->expiry = ddsrt_mtime_add_duration(ddsrt_time_monotonic(), DDS_SECS(PENDING_MATCH_EXPIRY_TIME)); + ddsrt_fibheap_insert(&pending_match_expiry_fhdef, &index->expiry_timers, match); + (void)resched_xevent_if_earlier(index->evt, match->expiry); + } + ddsrt_mutex_unlock(&index->lock); return match; } -static struct security_entity_match * remove_entity_match(struct dds_security_match_index *list, const ddsi_guid_t *src, const ddsi_guid_t *dst) +static void unregister_and_free_pending_match(dds_security_context *sc, struct pending_match *match) { - struct security_entity_match *match; - struct guid_pair guids; - ddsrt_avl_dpath_t path; + if (match->crypto_handle != 0) + { + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + const char *ename; + bool r = true; - guids.src = *src; - guids.dst = *dst; + switch (match->kind) + { + case EK_PROXY_PARTICIPANT: + break; + case EK_PROXY_READER: + ename = "reader"; + r = sc->crypto_context->crypto_key_factory->unregister_datareader(sc->crypto_context->crypto_key_factory, match->crypto_handle, &exception); + break; + case EK_PROXY_WRITER: + ename = "writer"; + r = sc->crypto_context->crypto_key_factory->unregister_datawriter(sc->crypto_context->crypto_key_factory, match->crypto_handle, &exception); + break; + default: + assert(0); + break; + } + if (!r) + EXCEPTION_ERROR(sc, &exception, "Failed to unregister remote %s crypto "PGUIDFMT" related to "PGUIDFMT, ename, PGUID(match->guids.remote_guid), PGUID(match->guids.local_guid)); + } + free_pending_match(match); +} - ddsrt_mutex_lock(&list->lock); - match = ddsrt_avl_lookup_dpath(&entity_match_treedef, &list->matches, &guids, &path); +static void delete_pending_match(struct pending_match_index *index, struct pending_match *match) +{ + ddsrt_mutex_lock(&index->lock); + ddsrt_avl_delete(&pending_match_index_treedef, &index->pending_matches, match); + if (match->expiry.v != DDS_NEVER) + ddsrt_fibheap_delete(&pending_match_expiry_fhdef, &index->expiry_timers, match); + free_pending_match(match); + ddsrt_mutex_unlock(&index->lock); +} + +static void pending_match_expiry_cb(struct xevent *xev, void *varg, ddsrt_mtime_t tnow) +{ + struct pending_match_index *index = varg; + + ddsrt_mutex_lock(&index->lock); + struct pending_match *match = ddsrt_fibheap_min(&pending_match_expiry_fhdef, &index->expiry_timers); + while (match && match->expiry.v <= tnow.v) + { + ddsrt_fibheap_delete(&pending_match_expiry_fhdef, &index->expiry_timers, match); + ddsrt_avl_delete(&pending_match_index_treedef, &index->pending_matches, match); + unregister_and_free_pending_match(index->gv->security_context, match); + match = ddsrt_fibheap_min(&pending_match_expiry_fhdef, &index->expiry_timers); + } if (match) - ddsrt_avl_delete_dpath(&entity_match_treedef, &list->matches, match, &path); - ddsrt_mutex_unlock(&list->lock); - - return match; + resched_xevent_if_earlier(xev, match->expiry); + ddsrt_mutex_unlock(&index->lock); } -static struct dds_security_match_index * security_match_index_new(void) +static void clear_pending_matches_by_local_guid(dds_security_context *sc, struct pending_match_index *index, const ddsi_guid_t *local_guid) { - struct dds_security_match_index *list; + struct pending_match *match; - list = ddsrt_malloc (sizeof(*list)); - ddsrt_mutex_init (&list->lock); - ddsrt_avl_init (&entity_match_treedef, &list->matches); - return list; -} - -static void entity_match_free_wrapper(void *arg) -{ - struct security_entity_match *match = arg; - entity_match_free(match); -} - -static void security_match_index_free(struct dds_security_match_index *list) -{ - if (list) + ddsrt_mutex_lock(&index->lock); + match = ddsrt_avl_find_min(&pending_match_index_treedef, &index->pending_matches); + while (match) { - ddsrt_avl_free (&entity_match_treedef, &list->matches, entity_match_free_wrapper); - ddsrt_mutex_destroy(&list->lock); - ddsrt_free(list); + struct pending_match *next = ddsrt_avl_find_succ(&pending_match_index_treedef, &index->pending_matches, match); + if (guid_compare(&match->guids.local_guid, local_guid) == 0) + { + ddsrt_avl_delete(&pending_match_index_treedef, &index->pending_matches, match); + if (match->expiry.v != DDS_NEVER) + ddsrt_fibheap_delete(&pending_match_expiry_fhdef, &index->expiry_timers, match); + next = ddsrt_avl_lookup_succ(&pending_match_index_treedef, &index->pending_matches, &match->guids); + unregister_and_free_pending_match(sc, match); + } + match = next; } + ddsrt_mutex_unlock(&index->lock); +} + +static void clear_pending_matches_by_remote_guid(dds_security_context *sc, struct pending_match_index *index, const ddsi_guid_t *remote_guid) +{ + struct guid_pair template = { .remote_guid = *remote_guid, .local_guid = {.prefix.u = {0, 0, 0}, .entityid.u = 0} }; + struct pending_match *match; + + ddsrt_mutex_lock(&index->lock); + match = ddsrt_avl_lookup_succ(&pending_match_index_treedef, &index->pending_matches, &template); + while (match && guid_compare(&match->guids.remote_guid, remote_guid) == 0) + { + struct pending_match *next = ddsrt_avl_lookup_succ(&pending_match_index_treedef, &index->pending_matches, &match->guids); + ddsrt_avl_delete(&pending_match_index_treedef, &index->pending_matches, match); + if (match->expiry.v != DDS_NEVER) + ddsrt_fibheap_delete(&pending_match_expiry_fhdef, &index->expiry_timers, match); + unregister_and_free_pending_match(sc, match); + match = next; + } + ddsrt_mutex_unlock(&index->lock); +} + +static void pending_match_index_init(const struct ddsi_domaingv *gv, struct pending_match_index *index) +{ + ddsrt_mutex_init(&index->lock); + ddsrt_avl_init(&pending_match_index_treedef, &index->pending_matches); + ddsrt_fibheap_init(&pending_match_expiry_fhdef, &index->expiry_timers); + index->gv = gv; + index->evt = qxev_callback(gv->xevents, DDSRT_MTIME_NEVER, pending_match_expiry_cb, index);; +} + +static void pending_match_index_deinit(struct pending_match_index *index) +{ + delete_xevent_callback(index->evt); + ddsrt_mutex_destroy(&index->lock); + assert(ddsrt_avl_is_empty(&index->pending_matches)); + ddsrt_avl_free(&pending_match_index_treedef, &index->pending_matches, 0); } static struct pp_proxypp_match * pp_proxypp_match_new(struct proxy_participant *proxypp, DDS_Security_ParticipantCryptoHandle proxypp_crypto_handle) @@ -420,16 +542,12 @@ static void pp_proxypp_unrelate(struct dds_security_context *sc, struct particip static void proxypp_pp_unrelate(struct dds_security_context *sc, struct proxy_participant *proxypp, const ddsi_guid_t *pp_guid, int64_t pp_crypto_handle) { + DDSRT_UNUSED_ARG(pp_guid); if (proxypp->sec_attr) { struct proxypp_pp_match *pm; - struct security_entity_match *match; ddsrt_avl_dpath_t dpath; - match = remove_entity_match(proxypp->e.gv->security_matches, &proxypp->e.guid, pp_guid); - if (match) - entity_match_free(match); - ddsrt_mutex_lock(&proxypp->sec_attr->lock); if ((pm = ddsrt_avl_lookup_dpath(&proxypp_pp_treedef, &proxypp->sec_attr->participants, &pp_crypto_handle, &dpath)) != NULL) { @@ -594,12 +712,12 @@ void q_omg_security_init (struct ddsi_domaingv *gv) ddsrt_mutex_init(&sc->partiticpant_index.lock); ddsrt_avl_cinit(&participant_index_treedef, &sc->partiticpant_index.participants); + pending_match_index_init(gv, &sc->security_matches); ddsrt_mutex_init (&sc->omg_security_lock); sc->logcfg = &gv->logconfig; gv->security_context = sc; - gv->security_matches = security_match_index_new(); ddsi_handshake_admin_init(gv); } @@ -628,27 +746,24 @@ void q_omg_security_stop (struct ddsi_domaingv *gv) ddsi_handshake_admin_stop(gv); } -void q_omg_security_deinit (struct ddsi_domaingv *gv) +void q_omg_security_deinit (struct dds_security_context *sc) +{ + pending_match_index_deinit(&sc->security_matches); +} + +void q_omg_security_free (struct ddsi_domaingv *gv) { dds_security_context *sc = gv->security_context; - assert (gv->security_context != NULL); - ddsrt_avl_cfree(&participant_index_treedef, &sc->partiticpant_index.participants, 0); ddsrt_mutex_destroy(&sc->partiticpant_index.lock); - if (gv->security_context->authentication_context != NULL && gv->security_context->access_control_context != NULL && gv->security_context->crypto_context != NULL){ - release_plugins (gv->security_context); + if (sc->authentication_context != NULL && sc->access_control_context != NULL && sc->crypto_context != NULL){ + release_plugins (sc); } - ddsi_handshake_admin_deinit(gv); - - security_match_index_free(gv->security_matches); - gv->security_matches = NULL; - - ddsrt_mutex_destroy (&gv->security_context->omg_security_lock); - - ddsrt_free(gv->security_context); + ddsrt_mutex_destroy (&sc->omg_security_lock); + ddsrt_free(sc); gv->security_context = NULL; } @@ -1018,6 +1133,8 @@ void q_omg_security_deregister_participant(struct participant *pp) qxev_nt_callback(pp->e.gv->xevents, cleanup_participant_sec_attributes, arg); } + clear_pending_matches_by_local_guid(sc, &sc->security_matches, &pp->e.guid); + pp->sec_attr = NULL; } @@ -1270,6 +1387,8 @@ void q_omg_security_deregister_writer(struct writer *wr) if (wr->sec_attr) { + clear_pending_matches_by_local_guid(sc, &sc->security_matches, &wr->e.guid); + if (wr->sec_attr->crypto_handle != DDS_SECURITY_HANDLE_NIL) { if (!sc->crypto_context->crypto_key_factory->unregister_datawriter(sc->crypto_context->crypto_key_factory, wr->sec_attr->crypto_handle, &exception)) @@ -1388,6 +1507,9 @@ void q_omg_security_deregister_reader(struct reader *rd) if (rd->sec_attr) { assert(sc); + + clear_pending_matches_by_local_guid(sc, &sc->security_matches, &rd->e.guid); + if (rd->sec_attr->crypto_handle != DDS_SECURITY_HANDLE_NIL) { if (!sc->crypto_context->crypto_key_factory->unregister_datareader(sc->crypto_context->crypto_key_factory, rd->sec_attr->crypto_handle, &exception)) @@ -1648,29 +1770,19 @@ bool q_omg_security_register_remote_participant(struct participant *pp, struct p GVTRACE("match pp->crypto=%"PRId64" proxypp->crypto=%"PRId64" permissions=%"PRId64"\n", pp->sec_attr->crypto_handle, crypto_handle, permissions_handle); match_proxypp_pp(pp, proxypp, permissions_handle, shared_secret); - GVTRACE("create proxypp-pp match pp="PGUIDFMT" proxypp="PGUIDFMT" lidh=%"PRId64, PGUID(pp->e.guid), PGUID(proxypp->e.guid), pp->sec_attr->local_identity_handle); + GVTRACE(" create proxypp-pp match pp="PGUIDFMT" proxypp="PGUIDFMT" lidh=%"PRId64"\n", PGUID(pp->e.guid), PGUID(proxypp->e.guid), pp->sec_attr->local_identity_handle); if (proxypp_is_rtps_protected(proxypp)) { - struct security_entity_match *m = find_or_create_entity_match(gv->security_matches, &proxypp->e.guid, &pp->e.guid); - m->crypto_handle = crypto_handle; - if (m->tokens) + struct pending_match *match = find_or_create_pending_entity_match(&sc->security_matches, EK_PROXY_PARTICIPANT, &proxypp->e.guid, &pp->e.guid, crypto_handle, NULL); + if (match->tokens) { - ret = sc->crypto_context->crypto_key_exchange->set_remote_participant_crypto_tokens(sc->crypto_context->crypto_key_exchange, pp->sec_attr->crypto_handle, crypto_handle, m->tokens, &exception); - if (ret) - { - struct security_entity_match *mx; - mx = remove_entity_match(proxypp->e.gv->security_matches, &proxypp->e.guid, &pp->e.guid); - assert(mx == m); - (void)mx; - entity_match_free(m); - GVTRACE("set participant tokens src("PGUIDFMT") to dst("PGUIDFMT") (by registering remote)\n", PGUID(proxypp->e.guid), PGUID(pp->e.guid)); - } + ret = sc->crypto_context->crypto_key_exchange->set_remote_participant_crypto_tokens(sc->crypto_context->crypto_key_exchange, pp->sec_attr->crypto_handle, crypto_handle, match->tokens, &exception); + if (!ret) + EXCEPTION_ERROR(sc, &exception, " Failed to set remote participant crypto tokens "PGUIDFMT" --> "PGUIDFMT, PGUID(proxypp->e.guid), PGUID(pp->e.guid)); else - { - EXCEPTION_ERROR(sc, &exception, "Failed to set remote participant crypto tokens "PGUIDFMT" --> "PGUIDFMT, PGUID(proxypp->e.guid), PGUID(pp->e.guid)); - ret = false; - } + GVTRACE(" set participant tokens src("PGUIDFMT") to dst("PGUIDFMT") (by registering remote)\n", PGUID(proxypp->e.guid), PGUID(pp->e.guid)); + delete_pending_match(&sc->security_matches, match); } else notify_handshake = true; @@ -1738,6 +1850,8 @@ void q_omg_security_deregister_remote_participant(struct proxy_participant *prox pm = next; } + clear_pending_matches_by_remote_guid(sc, &sc->security_matches, &proxypp->e.guid); + if (proxypp->sec_attr->crypto_handle != DDS_SECURITY_HANDLE_NIL) { if (!sc->crypto_context->crypto_key_factory->unregister_participant(sc->crypto_context->crypto_key_factory, proxypp->sec_attr->crypto_handle, &exception)) @@ -1820,36 +1934,33 @@ void q_omg_security_set_participant_crypto_tokens(struct participant *pp, struct DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; struct proxypp_pp_match *pm; DDS_Security_DatawriterCryptoTokenSeq *tseq; - struct security_entity_match *m; if (!sc) return; + tseq = DDS_Security_DataHolderSeq_alloc(); + q_omg_copyin_DataHolderSeq(tseq, tokens); + ddsrt_mutex_lock(&proxypp->sec_attr->lock); pm = ddsrt_avl_lookup (&proxypp_pp_treedef, &proxypp->sec_attr->participants, &pp->sec_attr->crypto_handle); ddsrt_mutex_unlock(&proxypp->sec_attr->lock); ddsrt_mutex_lock(&pp->e.lock); - m = find_or_create_entity_match(gv->security_matches, &proxypp->e.guid, &pp->e.guid); - - tseq = DDS_Security_DataHolderSeq_alloc(); - q_omg_copyin_DataHolderSeq(tseq, tokens); if (!pm) { GVTRACE("remember participant tokens src("PGUIDFMT") dst("PGUIDFMT")\n", PGUID(proxypp->e.guid), PGUID(pp->e.guid)); - m->tokens = tseq; + (void)find_or_create_pending_entity_match(&sc->security_matches, EK_PROXY_PARTICIPANT, &proxypp->e.guid, &pp->e.guid, 0, tseq); } else { if (sc->crypto_context->crypto_key_exchange->set_remote_participant_crypto_tokens(sc->crypto_context->crypto_key_exchange, pp->sec_attr->crypto_handle, proxypp->sec_attr->crypto_handle, tseq, &exception)) { - m->matched= true; - GVTRACE("set participant tokens src("PGUIDFMT") dst("PGUIDFMT")\n", PGUID(proxypp->e.guid), PGUID(pp->e.guid)); + GVTRACE(" set participant tokens src("PGUIDFMT") dst("PGUIDFMT")\n", PGUID(proxypp->e.guid), PGUID(pp->e.guid)); DDS_Security_DataHolderSeq_free(tseq); } else - EXCEPTION_ERROR(sc, &exception, "Failed to set remote participant crypto tokens "PGUIDFMT" for participant "PGUIDFMT, PGUID(proxypp->e.guid), PGUID(pp->e.guid)); + EXCEPTION_ERROR(sc, &exception, " Failed to set remote participant crypto tokens "PGUIDFMT" for participant "PGUIDFMT, PGUID(proxypp->e.guid), PGUID(pp->e.guid)); } ddsrt_mutex_unlock(&pp->e.lock); @@ -1986,64 +2097,68 @@ static bool q_omg_security_register_remote_writer_match(struct proxy_writer *pwr struct ddsi_domaingv *gv = pp->e.gv; struct dds_security_context *sc = q_omg_security_get_secure_context(pp); DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; - struct proxypp_pp_match *pm; - struct security_entity_match *match; + struct proxypp_pp_match *proxypp_match; + struct rd_pwr_match *match; bool send_tokens = false; + bool allowed = false; - *crypto_handle = 0; - - if ((pm = get_pp_proxypp_match_if_authenticated(pp, proxypp, pwr->e.guid.entityid)) == NULL) + if ((proxypp_match = get_pp_proxypp_match_if_authenticated(pp, proxypp, pwr->e.guid.entityid)) == NULL) return false; - /* TODO: the security_entity_match should be removed after the the received tokens are stored in the plugin. - * Currently the security_entity_match is also used to detect if a match between a reader and writer has - * already been completed. - */ ddsrt_mutex_lock(&rd->e.lock); - match = find_or_create_entity_match(gv->security_matches, &pwr->e.guid, &rd->e.guid); - if (match->matched) - *crypto_handle = match->crypto_handle; - else if (match->crypto_handle == 0) + if ((match = ddsrt_avl_lookup (&rd_writers_treedef, &rd->writers, &pwr->e.guid)) != NULL) + allowed = true; + else if (rd->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER) { - /* Generate writer crypto info. */ - match->crypto_handle = sc->crypto_context->crypto_key_factory->register_matched_remote_datawriter( - sc->crypto_context->crypto_key_factory, rd->sec_attr->crypto_handle, proxypp->sec_attr->crypto_handle, pm->shared_secret, &exception); + /* The builtin ParticipantVolatileSecure endpoints do not exchange tokens. + * Simulate that we already got them. */ - *crypto_handle = match->crypto_handle; - - if (match->crypto_handle == 0) - EXCEPTION_ERROR(sc, &exception, "Failed to register remote writer "PGUIDFMT" with reader "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); - else if (rd->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER) + *crypto_handle = sc->crypto_context->crypto_key_factory->register_matched_remote_datawriter( + sc->crypto_context->crypto_key_factory, rd->sec_attr->crypto_handle, proxypp->sec_attr->crypto_handle, proxypp_match->shared_secret, &exception); + if (*crypto_handle != 0) { - /* The builtin ParticipantVolatileSecure endpoints do not exchange tokens. - * Simulate that we already got them. */ - match->matched = true; - GVTRACE(" volatile secure reader: proxypp_crypto=%"PRId64" rd_crypto=%"PRId64" pwr_crypto=%"PRId64"\n", proxypp->sec_attr->crypto_handle, rd->sec_attr->crypto_handle, match->crypto_handle); + GVTRACE(" volatile secure reader: proxypp_crypto=%"PRId64" rd_crypto=%"PRId64" pwr_crypto=%"PRId64"\n", proxypp->sec_attr->crypto_handle, rd->sec_attr->crypto_handle, *crypto_handle); + allowed = true; } else + EXCEPTION_ERROR(sc, &exception, "Failed to register remote writer "PGUIDFMT" with reader "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); + } + else + { + struct pending_match *pending_match = find_or_create_pending_entity_match(&sc->security_matches, EK_PROXY_WRITER, &pwr->e.guid, &rd->e.guid, 0, NULL); + + /* Generate writer crypto info. */ + if (pending_match->crypto_handle == 0) { - send_tokens = true; - if (match->tokens) + *crypto_handle = sc->crypto_context->crypto_key_factory->register_matched_remote_datawriter( + sc->crypto_context->crypto_key_factory, rd->sec_attr->crypto_handle, proxypp->sec_attr->crypto_handle, proxypp_match->shared_secret, &exception); + if (*crypto_handle == 0) + EXCEPTION_ERROR(sc, &exception, "Failed to register remote writer "PGUIDFMT" with reader "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); + else { - if (sc->crypto_context->crypto_key_exchange->set_remote_datawriter_crypto_tokens( - sc->crypto_context->crypto_key_exchange, rd->sec_attr->crypto_handle, match->crypto_handle, match->tokens, &exception)) + pending_match->crypto_handle = *crypto_handle; + send_tokens = true; + if (pending_match->tokens) { - match->matched = true; - DDS_Security_DataHolderSeq_free(match->tokens); - match->tokens = NULL; - GVTRACE("match_remote_writer "PGUIDFMT" with reader "PGUIDFMT": tokens available\n", PGUID(pwr->e.guid), PGUID(rd->e.guid)); + if (!sc->crypto_context->crypto_key_exchange->set_remote_datawriter_crypto_tokens( + sc->crypto_context->crypto_key_exchange, rd->sec_attr->crypto_handle, *crypto_handle, pending_match->tokens, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to set remote writer crypto tokens "PGUIDFMT" --> "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); + else + { + GVTRACE("match_remote_writer "PGUIDFMT" with reader "PGUIDFMT": tokens available\n", PGUID(pwr->e.guid), PGUID(rd->e.guid)); + allowed = true; + } + delete_pending_match(&sc->security_matches, pending_match); } - else - EXCEPTION_ERROR(sc, &exception, "Failed to set remote writer crypto tokens "PGUIDFMT" --> "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); } } } ddsrt_mutex_unlock(&rd->e.lock); if (send_tokens) - (void)send_reader_crypto_tokens(rd, pwr, rd->sec_attr->crypto_handle, match->crypto_handle); + (void)send_reader_crypto_tokens(rd, pwr, rd->sec_attr->crypto_handle, *crypto_handle); - return match->matched; + return allowed; } bool q_omg_security_match_remote_writer_enabled(struct reader *rd, struct proxy_writer *pwr, int64_t *crypto_handle) @@ -2051,6 +2166,8 @@ bool q_omg_security_match_remote_writer_enabled(struct reader *rd, struct proxy_ struct ddsi_domaingv *gv = rd->e.gv; nn_security_info_t info; + *crypto_handle = 0; + if (!rd->sec_attr) return true; @@ -2106,21 +2223,23 @@ void q_omg_security_deregister_remote_writer_match(const struct ddsi_domaingv *g { struct dds_security_context *sc = gv->security_context; DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; - struct security_entity_match *match = NULL; if (m->crypto_handle != 0) { - match = remove_entity_match(gv->security_matches, &m->pwr_guid, rd_guid); - if (match) - { - assert(match->crypto_handle == m->crypto_handle); - if (!sc->crypto_context->crypto_key_factory->unregister_datawriter(sc->crypto_context->crypto_key_factory, match->crypto_handle, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to unregster remote writer "PGUIDFMT" for reader "PGUIDFMT, PGUID(m->pwr_guid), PGUID(*rd_guid)); - entity_match_free(match); - } + if (!sc->crypto_context->crypto_key_factory->unregister_datawriter(sc->crypto_context->crypto_key_factory, m->crypto_handle, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to unregister remote writer "PGUIDFMT" for reader "PGUIDFMT, PGUID(m->pwr_guid), PGUID(*rd_guid)); } } +void q_omg_security_deregister_remote_writer(const struct proxy_writer *pwr) +{ + struct ddsi_domaingv *gv = pwr->e.gv; + struct dds_security_context *sc = gv->security_context; + + if (q_omg_proxy_participant_is_secure(pwr->c.proxypp)) + clear_pending_matches_by_remote_guid(sc, &sc->security_matches, &pwr->e.guid); +} + bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *prd, uint32_t domain_id, struct participant *pp, bool *relay_only) { struct ddsi_domaingv *gv = pp->e.gv; @@ -2260,22 +2379,23 @@ void q_omg_security_deregister_remote_reader_match(const struct ddsi_domaingv *g { struct dds_security_context *sc = gv->security_context; DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; - struct security_entity_match *match = NULL; - if (m->crypto_handle) + if (m->crypto_handle != 0) { - match = remove_entity_match(gv->security_matches, &m->prd_guid, wr_guid); - if (match) - { - assert(match->crypto_handle == m->crypto_handle); - - if (!sc->crypto_context->crypto_key_factory->unregister_datareader(sc->crypto_context->crypto_key_factory, match->crypto_handle, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to unregister remote reader "PGUIDFMT" for writer "PGUIDFMT, PGUID(m->prd_guid), PGUID(*wr_guid)); - entity_match_free(match); - } + if (!sc->crypto_context->crypto_key_factory->unregister_datareader(sc->crypto_context->crypto_key_factory, m->crypto_handle, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to unregister remote reader "PGUIDFMT" for writer "PGUIDFMT, PGUID(m->prd_guid), PGUID(*wr_guid)); } } +void q_omg_security_deregister_remote_reader(const struct proxy_reader *prd) +{ + struct ddsi_domaingv *gv = prd->e.gv; + struct dds_security_context *sc = gv->security_context; + + if (q_omg_proxy_participant_is_secure(prd->c.proxypp)) + clear_pending_matches_by_remote_guid(sc, &sc->security_matches, &prd->e.guid); +} + static void send_writer_crypto_tokens(struct writer *wr, struct proxy_reader *prd, DDS_Security_DatawriterCryptoHandle local_crypto, DDS_Security_DatareaderCryptoHandle remote_crypto) { struct dds_security_context *sc = q_omg_security_get_secure_context(wr->c.pp); @@ -2309,66 +2429,70 @@ static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd struct ddsi_domaingv *gv = pp->e.gv; struct dds_security_context *sc = q_omg_security_get_secure_context(pp); DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; - struct proxypp_pp_match *pm; - struct security_entity_match *match; + struct proxypp_pp_match *proxypp_match; + struct wr_prd_match *match; bool send_tokens = false; + bool allowed = false; - *crypto_handle = 0; - - if ((pm = get_pp_proxypp_match_if_authenticated(pp, proxypp, prd->e.guid.entityid)) == NULL) + if ((proxypp_match = get_pp_proxypp_match_if_authenticated(pp, proxypp, prd->e.guid.entityid)) == NULL) return false; - /* TODO: the security_entity_match should be removed after the the received tokens are stored in the plugin. - * Currently the security_entity_match is also used to detect if a match between a reader and writer has - * already been completed. - */ ddsrt_mutex_lock(&wr->e.lock); - match = find_or_create_entity_match(gv->security_matches, &prd->e.guid, &wr->e.guid); - if (match->matched) - *crypto_handle = match->crypto_handle; - else if (match->crypto_handle == 0) + if ((match = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) + allowed = true; + else if (wr->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER || !wr->sec_attr->attr.is_submessage_protected) { - /* Generate writer crypto info. */ - match->crypto_handle = sc->crypto_context->crypto_key_factory->register_matched_remote_datareader( - sc->crypto_context->crypto_key_factory, wr->sec_attr->crypto_handle, proxypp->sec_attr->crypto_handle, pm->shared_secret, relay_only, &exception); + /* The builtin ParticipantVolatileSecure endpoints do not exchange tokens. + * Simulate that we already got them. */ - *crypto_handle = match->crypto_handle; - - if (match->crypto_handle == 0) - EXCEPTION_ERROR(sc, &exception, "Failed to register remote reader "PGUIDFMT" with writer "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); - else if (wr->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER) + *crypto_handle = sc->crypto_context->crypto_key_factory->register_matched_remote_datareader( + sc->crypto_context->crypto_key_factory, wr->sec_attr->crypto_handle, proxypp->sec_attr->crypto_handle, proxypp_match->shared_secret, relay_only, &exception); + if (*crypto_handle != 0) { - /* The builtin ParticipantVolatileSecure endpoints do not exchange tokens. - * Simulate that we already got them. */ - match->matched = true; - GVTRACE(" volatile secure writer: proxypp_crypto=%"PRId64" wr_crypto=%"PRId64" prd_crypto=%"PRId64"\n", proxypp->sec_attr->crypto_handle, wr->sec_attr->crypto_handle, match->crypto_handle); + GVTRACE(" match_remote_reader: proxypp_crypto=%"PRId64" wr_crypto=%"PRId64" prd_crypto=%"PRId64"\n", proxypp->sec_attr->crypto_handle, wr->sec_attr->crypto_handle, *crypto_handle); + send_tokens = (wr->e.guid.entityid.u != NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER); + allowed = true; } else + EXCEPTION_ERROR(sc, &exception, "Failed to register remote reader "PGUIDFMT" with writer "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); + } + else + { + struct pending_match *pending_match = find_or_create_pending_entity_match(&sc->security_matches, EK_PROXY_READER, &prd->e.guid, &wr->e.guid, 0, NULL); + + /* Generate writer crypto info. */ + if (pending_match->crypto_handle == 0) { - send_tokens = true; - if (match->tokens) + *crypto_handle = sc->crypto_context->crypto_key_factory->register_matched_remote_datareader( + sc->crypto_context->crypto_key_factory, wr->sec_attr->crypto_handle, proxypp->sec_attr->crypto_handle, proxypp_match->shared_secret, relay_only, &exception); + if (*crypto_handle == 0) + EXCEPTION_ERROR(sc, &exception, "Failed to register remote reader "PGUIDFMT" with writer "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); + else { - if (sc->crypto_context->crypto_key_exchange->set_remote_datareader_crypto_tokens( - sc->crypto_context->crypto_key_exchange, wr->sec_attr->crypto_handle, match->crypto_handle, match->tokens, &exception)) + pending_match->crypto_handle = *crypto_handle; + send_tokens = true; + GVTRACE(" register_remote_reader_match: proxypp_crypto=%"PRId64" wr_crypto=%"PRId64" prd_crypto=%"PRId64"\n", proxypp->sec_attr->crypto_handle, wr->sec_attr->crypto_handle, *crypto_handle); + if (pending_match->tokens) { - match->matched = true; - DDS_Security_DataHolderSeq_free(match->tokens); - match->tokens = NULL;; - GVTRACE("match_remote_reader "PGUIDFMT" with writer "PGUIDFMT": tokens available\n", PGUID(prd->e.guid), PGUID(wr->e.guid)); + if (!sc->crypto_context->crypto_key_exchange->set_remote_datareader_crypto_tokens( + sc->crypto_context->crypto_key_exchange, wr->sec_attr->crypto_handle, *crypto_handle, pending_match->tokens, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to set remote reader crypto tokens "PGUIDFMT" --> "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); + else + { + GVTRACE(" match_remote_reader "PGUIDFMT" with writer "PGUIDFMT": tokens available\n", PGUID(prd->e.guid), PGUID(wr->e.guid)); + allowed = true; + } + delete_pending_match(&sc->security_matches, pending_match); } - else - EXCEPTION_ERROR(sc, &exception, "Failed to set remote reader crypto tokens "PGUIDFMT" --> "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); } - else if (!wr->sec_attr->attr.is_submessage_protected) - match->matched = true; } } ddsrt_mutex_unlock(&wr->e.lock); if (send_tokens) - (void)send_writer_crypto_tokens(wr, prd, wr->sec_attr->crypto_handle, match->crypto_handle); + (void)send_writer_crypto_tokens(wr, prd, wr->sec_attr->crypto_handle, *crypto_handle); - return match->matched; + return allowed; } bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_reader *prd, bool relay_only, int64_t *crypto_handle) @@ -2376,6 +2500,8 @@ bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_ struct ddsi_domaingv *gv = wr->e.gv; nn_security_info_t info; + *crypto_handle = 0; + if (!wr->sec_attr) return true; @@ -2432,43 +2558,35 @@ void q_omg_security_set_remote_writer_crypto_tokens(struct reader *rd, const dds struct dds_security_context *sc = q_omg_security_get_secure_context(rd->c.pp); struct ddsi_domaingv *gv = rd->e.gv; DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; - struct security_entity_match *match; + struct pending_match *match; struct proxy_writer *pwr = NULL; + int64_t crypto_handle = 0; if (!sc) return; - ddsrt_mutex_lock(&rd->e.lock); - match = find_or_create_entity_match(gv->security_matches, pwr_guid, &rd->e.guid); - if (match->matched) - { - ddsrt_mutex_unlock(&rd->e.lock); - return; - } - DDS_Security_DatawriterCryptoTokenSeq * tseq = DDS_Security_DataHolderSeq_alloc(); q_omg_copyin_DataHolderSeq(tseq, tokens); - if ((pwr = entidx_lookup_proxy_writer_guid(gv->entity_index, pwr_guid)) == NULL || match->crypto_handle == 0 ) - { + ddsrt_mutex_lock(&rd->e.lock); + match = find_or_create_pending_entity_match(&sc->security_matches, EK_PROXY_WRITER, pwr_guid, &rd->e.guid, 0, tseq); + if ((pwr = entidx_lookup_proxy_writer_guid(gv->entity_index, pwr_guid)) == NULL || match->crypto_handle == 0) GVTRACE("remember writer tokens src("PGUIDFMT") dst("PGUIDFMT")\n", PGUID(*pwr_guid), PGUID(rd->e.guid)); - match->tokens = tseq; - } else { - if (sc->crypto_context->crypto_key_exchange->set_remote_datawriter_crypto_tokens(sc->crypto_context->crypto_key_exchange, rd->sec_attr->crypto_handle, match->crypto_handle, tseq, &exception)) + if (!sc->crypto_context->crypto_key_exchange->set_remote_datawriter_crypto_tokens(sc->crypto_context->crypto_key_exchange, rd->sec_attr->crypto_handle, match->crypto_handle, tseq, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to set remote writer crypto tokens "PGUIDFMT" for reader "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); + else { GVTRACE("set_remote_writer_crypto_tokens "PGUIDFMT" with reader "PGUIDFMT"\n", PGUID(pwr->e.guid), PGUID(rd->e.guid)); - match->matched = true; + crypto_handle = match->crypto_handle; } - else - EXCEPTION_ERROR(sc, &exception, "Failed to set remote writer crypto tokens "PGUIDFMT" for reader "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); - DDS_Security_DataHolderSeq_free(tseq); + delete_pending_match(&sc->security_matches, match); } ddsrt_mutex_unlock(&rd->e.lock); - if (match->matched) - connect_reader_with_proxy_writer_secure(rd, pwr, ddsrt_time_monotonic (), match->crypto_handle); + if (crypto_handle != 0) + connect_reader_with_proxy_writer_secure(rd, pwr, ddsrt_time_monotonic (), crypto_handle); if (pwr) notify_handshake_recv_token(rd->c.pp, pwr->c.proxypp); @@ -2479,46 +2597,38 @@ void q_omg_security_set_remote_reader_crypto_tokens(struct writer *wr, const dds struct dds_security_context *sc = q_omg_security_get_secure_context(wr->c.pp); struct ddsi_domaingv *gv = wr->e.gv; DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; - struct security_entity_match *match; + struct pending_match *match; struct proxy_reader *prd = NULL; + int64_t crypto_handle = 0; if (!sc) - return; - - ddsrt_mutex_lock(&wr->e.lock); - match = find_or_create_entity_match(gv->security_matches, prd_guid, &wr->e.guid); - if (match->matched) - { - ddsrt_mutex_unlock(&wr->e.lock); return; - } - DDS_Security_DatawriterCryptoTokenSeq *tseq = DDS_Security_DataHolderSeq_alloc(); - q_omg_copyin_DataHolderSeq(tseq, tokens); + DDS_Security_DatawriterCryptoTokenSeq *tseq = DDS_Security_DataHolderSeq_alloc(); + q_omg_copyin_DataHolderSeq(tseq, tokens); - if (((prd = entidx_lookup_proxy_reader_guid(gv->entity_index, prd_guid)) == NULL) || (match->crypto_handle == 0)) - { - GVTRACE("remember reader tokens src("PGUIDFMT") dst("PGUIDFMT")\n", PGUID(*prd_guid), PGUID(wr->e.guid)); - match->tokens = tseq; - } - else - { - if (sc->crypto_context->crypto_key_exchange->set_remote_datareader_crypto_tokens(sc->crypto_context->crypto_key_exchange, wr->sec_attr->crypto_handle, match->crypto_handle, tseq, &exception)) - { - GVTRACE("set_remote_reader_crypto_tokens "PGUIDFMT" with writer "PGUIDFMT"\n", PGUID(prd->e.guid), PGUID(wr->e.guid)); - match->matched = true; - } - else - EXCEPTION_ERROR(sc, &exception, "Failed to set remote reader crypto tokens "PGUIDFMT" for writer "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); - DDS_Security_DataHolderSeq_free(tseq); - } - ddsrt_mutex_unlock(&wr->e.lock); + ddsrt_mutex_lock(&wr->e.lock); + match = find_or_create_pending_entity_match(&sc->security_matches, EK_PROXY_READER, prd_guid, &wr->e.guid, 0, tseq); + if (((prd = entidx_lookup_proxy_reader_guid(gv->entity_index, prd_guid)) == NULL) || (match->crypto_handle == 0)) + GVTRACE("remember reader tokens src("PGUIDFMT") dst("PGUIDFMT")\n", PGUID(*prd_guid), PGUID(wr->e.guid)); + else + { + if (!sc->crypto_context->crypto_key_exchange->set_remote_datareader_crypto_tokens(sc->crypto_context->crypto_key_exchange, wr->sec_attr->crypto_handle, match->crypto_handle, tseq, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to set remote reader crypto tokens "PGUIDFMT" for writer "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); + else + { + GVTRACE("set_remote_reader_crypto_tokens "PGUIDFMT" with writer "PGUIDFMT"\n", PGUID(prd->e.guid), PGUID(wr->e.guid)); + crypto_handle = match->crypto_handle; + } + delete_pending_match(&sc->security_matches, match); + } + ddsrt_mutex_unlock(&wr->e.lock); - if (match->matched) - connect_writer_with_proxy_reader_secure(wr, prd, ddsrt_time_monotonic (), match->crypto_handle); + if (crypto_handle != 0) + connect_writer_with_proxy_reader_secure(wr, prd, ddsrt_time_monotonic (), crypto_handle); - if (prd) - notify_handshake_recv_token(wr->c.pp, prd->c.proxypp); + if (prd) + notify_handshake_recv_token(wr->c.pp, prd->c.proxypp); } bool q_omg_reader_is_discovery_protected(const struct reader *rd) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 826124f..dfd2433 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -5638,6 +5638,9 @@ static void gc_delete_proxy_writer (struct gcreq *gcreq) local_reader_ary_fini (&pwr->rdary); if (pwr->c.xqos->liveliness.lease_duration != DDS_INFINITY) lease_free (pwr->lease); +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deregister_remote_writer(pwr); +#endif proxy_endpoint_common_fini (&pwr->e, &pwr->c); nn_defrag_free (pwr->defrag); nn_reorder_free (pwr->reorder); @@ -5869,6 +5872,9 @@ static void gc_delete_proxy_reader (struct gcreq *gcreq) writer_drop_connection (&m->wr_guid, prd); free_prd_wr_match (m); } +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deregister_remote_reader(prd); +#endif proxy_endpoint_common_fini (&prd->e, &prd->c); ddsrt_free (prd); } diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index cabcf49..46571cc 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -1199,8 +1199,6 @@ int rtps_init (struct ddsi_domaingv *gv) * the entities (see DDS Security spec chapter 8.8.8.1). */ add_property_to_xqos(&gv->builtin_volatile_xqos_rd, "dds.sec.builtin_endpoint_name", "BuiltinParticipantVolatileMessageSecureReader"); add_property_to_xqos(&gv->builtin_volatile_xqos_wr, "dds.sec.builtin_endpoint_name", "BuiltinParticipantVolatileMessageSecureWriter"); - - q_omg_security_init(gv); #endif ddsrt_mutex_init (&gv->sertopics_lock); @@ -1470,6 +1468,10 @@ int rtps_init (struct ddsi_domaingv *gv) #endif ); +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_init(gv); +#endif + gv->as_disc = new_addrset (); if (gv->config.allowMulticast & AMC_SPDP) add_to_addrset (gv, gv->as_disc, &gv->loc_spdp_mc); @@ -1559,7 +1561,8 @@ err_unicast_sockets: ddsrt_mutex_destroy (&gv->sertopics_lock); #ifdef DDSI_INCLUDE_SECURITY q_omg_security_stop (gv); // should be a no-op as it starts lazily - q_omg_security_deinit (gv); + q_omg_security_deinit(gv->security_context); + q_omg_security_free (gv); ddsi_xqos_fini (&gv->builtin_stateless_xqos_wr); ddsi_xqos_fini (&gv->builtin_stateless_xqos_rd); ddsi_xqos_fini (&gv->builtin_volatile_xqos_wr); @@ -1835,6 +1838,10 @@ void rtps_fini (struct ddsi_domaingv *gv) nn_dqueue_free (gv->user_dqueue); #endif +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deinit (gv->security_context); +#endif + xeventq_free (gv->xevents); if (gv->config.xpack_send_async) @@ -1918,7 +1925,7 @@ void rtps_fini (struct ddsi_domaingv *gv) ddsrt_mutex_destroy (&gv->sertopics_lock); #ifdef DDSI_INCLUDE_SECURITY - q_omg_security_deinit (gv); + q_omg_security_free (gv); ddsi_xqos_fini (&gv->builtin_stateless_xqos_wr); ddsi_xqos_fini (&gv->builtin_stateless_xqos_rd); ddsi_xqos_fini (&gv->builtin_volatile_xqos_wr);