Remove temporarily stored crypto handles and tokens after entities are matched
Signed-off-by: Marcel Jordense <marcel.jordense@adlinktech.com>
This commit is contained in:
parent
829e33ac82
commit
534eac2a11
5 changed files with 439 additions and 290 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue